PHP:简单HTML Dom解析器-解析带有标题/不均匀正文行的HTML表

PHP:简单HTML Dom解析器-解析带有标题/不均匀正文行的HTML表,php,html,parsing,simple-html-dom,Php,Html,Parsing,Simple Html Dom,我有一个HTML表格,格式如下:如您所见,第一个标题1有一行1与之关联。第二个标题2有两行—与之关联的第2行和第3行。标题3有与之关联的第4行、第5行和第6行 <table> <thead> <tr> <th>Header 1</th> </tr> </thead> <tbody> <tr> <td>

我有一个HTML表格,格式如下:如您所见,第一个标题1有一行1与之关联。第二个标题2有两行—与之关联的第2行和第3行。标题3有与之关联的第4行、第5行和第6行

<table>
<thead>
    <tr>
        <th>Header 1</th>
    </tr>
</thead>
<tbody>
        <tr>
            <td>
                Row 1
            </td>
        </tr>
</tbody>
<thead>
    <tr>
        <th>Header 2</th>
    </tr>
</thead>
<tbody>
        <tr>
            <td>
                Row 2
            </td>
        </tr>
        <tr>
            <td>
                Row 3
            </td>
        </tr>

</tbody>
<thead>
    <tr>
        <th>Header 3</th>
    </tr>
</thead>
<tbody>
        <tr>
            <td>
                Row 4
            </td>
        </tr>
        <tr>
            <td>
                Row 5
            </td>
        </tr>
        <tr>
            <td>
                Row 6
            </td>
        </tr>
</tbody>

当我使用解析器获取标记时,所有标记都存储在一个数组中。当我执行foreach循环时,所有其他标记都存储在另一个数组中。当我循环时,如何保持标题与行的关联?

您可以使用标准的DOMDocument接口来实现这一点。如果HTML存储在变量
$HTML
中,请执行以下操作:

$dom = new DOMDocument();
$dom->loadHTML($html);
foreach ($dom->getElementsByTagName('tr') as $row) {
    if ($row->parentNode->tagName === 'thead') $arr[] = [];
    $arr[count($arr)-1][] = trim($row->textContent);
}
运行上述命令后,变量
$arr
将包含以下内容:

[
    ['Header 1', 'Row 1'],
    ['Header 2', 'Row 2', 'Row 3'],
    ['Header 3', 'Row 4', 'Row 5', 'Row 6']
]

您可以使用标准的DOMDocument接口来实现这一点。如果HTML存储在变量
$HTML
中,请执行以下操作:

$dom = new DOMDocument();
$dom->loadHTML($html);
foreach ($dom->getElementsByTagName('tr') as $row) {
    if ($row->parentNode->tagName === 'thead') $arr[] = [];
    $arr[count($arr)-1][] = trim($row->textContent);
}
运行上述命令后,变量
$arr
将包含以下内容:

[
    ['Header 1', 'Row 1'],
    ['Header 2', 'Row 2', 'Row 3'],
    ['Header 3', 'Row 4', 'Row 5', 'Row 6']
]

如果看不到现有的php代码,就很难准确地说出如何更改现有的php代码。但类似这样的东西适用于您的用例:

//Assuming $html has been set to your html block
$heads = $html->find('thead');
$result = array();

foreach($heads as $head){
    $headerText = $head->find('th')[0]->innerText;
    $result[$headerText] = array();
    $rows = $head->next_sibling()->find('td');
    foreach($rows as $row){
        $result[$headerText][] = $row->innerText;
    }
}

//Output
foreach($result as $header => $rows){
    echo $header . ': ' . implode(',', $rows);
}
需要注意的是,上面是一个简单的示例,说明了您想要做什么。这是一个相当幼稚的实现。例如,它假设一个给定的
thead
只会有一个
th

另外,如果回送它确实是您想要做的全部,那么直接在解析循环中回送会更有效。我分离了输出,因为我假设您不只是想将其打印到屏幕上


请注意,使用本机dom解析器执行类似操作相当简单,我假设您出于其他原因需要使用简单的html dom。

如果没有看到现有的php代码,很难准确地说出如何更改现有的内容。但类似这样的东西适用于您的用例:

//Assuming $html has been set to your html block
$heads = $html->find('thead');
$result = array();

foreach($heads as $head){
    $headerText = $head->find('th')[0]->innerText;
    $result[$headerText] = array();
    $rows = $head->next_sibling()->find('td');
    foreach($rows as $row){
        $result[$headerText][] = $row->innerText;
    }
}

//Output
foreach($result as $header => $rows){
    echo $header . ': ' . implode(',', $rows);
}
需要注意的是,上面是一个简单的示例,说明了您想要做什么。这是一个相当幼稚的实现。例如,它假设一个给定的
thead
只会有一个
th

另外,如果回送它确实是您想要做的全部,那么直接在解析循环中回送会更有效。我分离了输出,因为我假设您不只是想将其打印到屏幕上


请注意,使用本机dom解析器执行类似操作将非常简单,我假设您出于其他原因需要使用简单的html dom。

您为什么不使用内置的DOMDocument接口?请显示您的代码。你指的是哪一个foreach?你为什么不使用内置的DOMDocument接口?请出示你的代码。你指的是哪一种?谢谢,它工作得很好@trincot的解决方案也很有效。谢谢,它非常有效@特林科特的解决方案也起了作用。