DOMXpath & PHP:如何将一堆 <li> 包裹在 <ul> 中

DOMXpath & PHP: how to wrap a bunch of <li> inside an <ul>

我有一个 html 文档,带有这个不太好的标记,没有 'ul':

<p>Lorem</p>
<p>Ipsum...</p>
<li class='item'>...</li>
<li class='item'>...</li>
<li class='item'>...</li>
<div>...</div>

我现在正在尝试 "grab" 所有 li 元素并将它们包装在一个 ul 列表中,我想使用 PHP 和 DOMXPath 将它们放在同一位置。我设法找到并 "remove" li 元素:

$elements =  $xpath->query('//li[@class="item"]');

$wrapper = $document->createElement('ul');
foreach($elements as $child) {
    $wrapper->appendChild($child);
}

这是您需要的。您可能需要为您的真实 HTML.

调整 XPath 查询
$document = new DOMDocument;

// We don't want to bother with white spaces
$document->preserveWhiteSpace = false;

$html = <<<EOT
<p>Lorem</p>
<p>Ipsum...</p>
<li class='item'>...</li>
<li class='item'>...</li>
<li class='item'>last...</li>
<div>...</div>
EOT;

$document->LoadHtml($html);

$xpath = new DOMXPath($document);

$elements =  $xpath->query('//li[@class="item"]');

// Saves a reference to the Node that is positioned right after our li's
$ref = $xpath->query('//li[@class="item"][last()]')->item(0)->nextSibling;

$wrapper = $document->createElement('ul');
foreach($elements as $child) {
    $wrapper->appendChild($child);
} 

$ref->parentNode->insertBefore($wrapper, $ref);

echo $document->saveHTML();

运行 示例:https://repl.it/B3UO/24

也许你可以得到第一个<li>parentNode,然后使用insertBefore的方法:

$html = <<<HTML
<p>Lorem</p>
<p>Ipsum...</p>
<li class='item'>...</li>
<li class='item'>...</li>
<li class='item'>...</li>
<div>...</div>
HTML;
$doc = new DOMDocument();
$doc->loadHTML($html);

$xpath = new DOMXpath($doc);

$elements = $xpath->query('//li[@class="item"]');

$wrapper = $doc->createElement('ul');
$elements->item(0)->parentNode->insertBefore(
    $wrapper, $elements->item(0)
);

foreach($elements as $child) {
    $wrapper->appendChild($child);
}

echo $doc->saveHTML();

Demo