php如何使用dom从php中的html中提取递归列表?

时间:2018-08-23 13:12:49

标签: php dom xpath

这是HTML中的以下递归列表

<ul>
<li>
     <ul>
     <li>Sub-Item 1</li>
     <li>Sub-Item 2</li>
     </ul>
</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>

我想提取主ul的第一个和第三个列表元素。

这是代码

$xpath = new DOMXPath($dom);

// to get first list item of main ul <ul><li>Sub-Item 1<li>
 //    <li>Sub-Item 2<li></ul>
$nav =$xpath->query('//li[1]');
echo $nav->item(0)->nodeValue;

//to get second list itrm of main ul <li>Item 3</li>
$nav =$xpath->query('//li[3]');
echo $nav->item(0)->nodeValue;

但是我将其作为输出

   <li>Sub-Item 1<li>
    <li>Sub-Item 2<li>

    <li>Sub-Item 3<li> 

它正在考虑第二个XPath查询中的子列表。有人可以告诉我什么是正确的查询。我是dom的新手。

编辑:主要目标是将其保存为PHP数组,如下所示

 Array
(
    [0] => Array
        (
            [0] => Sub-Item 1
            [1] => Sub-Item 2
        )

    [1] => Item 2
    [2] => Item 3
)

2 个答案:

答案 0 :(得分:0)

$ rez = $ xpath-> query('(// ul / li)[1]'); //第一个

$ rez = $ xpath-> query('(// ul / li)[last()]'); //最后一次

答案 1 :(得分:0)

Xpath不会重新排列节点,因此无法使用嵌套结构。返回值是节点列表,它们在文档中保持其位置(父,子,...)。要创建递归数组结构,您将需要更多的PHP逻辑:

function readListElement(\DOMElement $li) {
    // get an xpath instance
    $xpath = new DOMXpath($li->ownerDocument);
    // check if the node has an ul child
    if ($xpath->evaluate('count(ul) = 0', $li)) {
        // if not return the text inside
        return $li->textContent;
    }
    // otherwise 
    $result = [];
    // iterate the inner ul li elements
    foreach ($xpath->evaluate('ul/li', $li) as $liChild) {
        // and call the function itself
        $result[] = readListElement($liChild);
    }
    return $result;
}

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);

// get the top level ul (has no ul ancestor)
foreach ($xpath->evaluate('//ul[not(ancestor::ul)]') as $ul) {
    $result = [];
    foreach ($xpath->evaluate('li', $ul) as $li) {
      $result[] = readListElement($li);
    }
    var_dump($result);
}

输出:

array(3) {
  [0]=>
  array(2) {
    [0]=>
    string(10) "Sub-Item 1"
    [1]=>
    string(10) "Sub-Item 2" 
  } 
  [1]=> 
  string(6) "Item 2" 
  [2]=> 
  string(6) "Item 3" 
}