我有一个这样的结构:
<h3><span class="header" id="first_set">My Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<h3><span class="header" id="second_set">My Second Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<h3><span class="header" id="third_set">My Third Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
我使用 DOMDocument 从网页中提取了此内容。我需要遍历9000个页面,这些页面在其中都有细微的变化。因此,“第三标题”实际上在某些情况下可能是一个表,而不是另一个h3。
我要准确地做的是将div环绕在第二个标题上,并在div不再找到</ul>
标签时关闭div(因此,直到它遇到不是ul标签为止>)。因此结果将是这样的:
<h3><span class="header" id="first_set">My Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<div class="second_heading">
<h3><span class="header" id="second_set">My Second Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
</div>
<h3><span class="header" id="third_set">My Third Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
我在考虑preg_replace
,但不确定如何执行“找到最后一个关闭ul标签时关闭div”的逻辑。
答案 0 :(得分:1)
您可以在继续使用DOMDocument
的同时实现这一目标。我假设您有一个名为$node
的变量,它是您在问题中显示的HTML上方的节点。在这种情况下,您可以使用DOMXPath
找到该元素的所有子节点,然后对其进行迭代,直到到达第二个<h3>
并将其和所有后续的<ul>
元素附加到新的<div>
,直到到达第二个标头之后的第一个非<ul>
元素为止:
$div = $doc->createElement('div');
$xpath = new DOMXPath($doc);
$headers = 0;
foreach ($xpath->query('./*', $node) as $child) {
echo $child->nodeName;
switch ($child->nodeName) {
case 'h3':
$headers++;
if ($headers == 2) {
$node->replaceChild($div, $child);
$div->appendChild($child);
}
else if ($headers == 3) {
break 2;
}
break;
case 'ul':
if ($headers == 2) $div->appendChild($child);
break;
default:
// if a non-ul element after the 2nd header, exit the loop
if ($headers == 2) break 2;
break;
}
}