有没有一种简单的方法来获取DomDocument和DomXPath的子元素?

时间:2014-05-18 20:44:40

标签: php parsing html-parsing domdocument domxpath

假设我有这样的HTML:

<div id="container">
    <li class="list">
        Test text
    </li>
</div>

我想获得li的内容。

我可以使用以下代码获取容器div的内容:

$html = '
<div id="container">
    <li class="list">
        Test text
    </li>
</div>';

$dom = new \DomDocument;
$dom->loadHTML($html);

$xpath = new \DomXPath($dom);

echo $dom->saveHTML($xpath->query("//div[@id='container']")->item(0));

我希望通过简单地将它添加到查询中来获取子元素的内容(就像你在simpleHtmlDom中可以做到的那样):

echo $dom->saveHTML($xpath->query("//div[@id='container'] li[@class='list']")->item(0));

但是一个警告(后面是一个致命的错误)被抛出,说:

 Warning: DOMXPath::query(): Invalid expression ...

我知道做我想做的唯一方法是:

$html = '
<div id="container">
    <li class="list">
        Test text
    </li>
</div>';

$dom = new \DomDocument;
$dom->loadHTML($html);
$xpath = new \DomXPath($dom);

$dom2 = new \DomDocument;
$dom2->loadHTML(trim($dom->saveHTML($xpath->query("//div[@id='container']")->item(0))));
$xpath2       = new \DomXPath($dom2);

echo $xpath2->query("//li[@class='list']")->item(0)->nodeValue;

然而,这只是获取li内容的大量代码,问题是项目嵌套得更深(如果我想得到`div#container ul.container li。 list)我必须继续添加越来越多的代码。

使用simpleHtmlDom,我所要做的就是:

$html->find('div#container li.list', 0);

我错过了使用DomDocument和DomXPath做事的简单方法,还是真的很难?

2 个答案:

答案 0 :(得分:1)

你最初的尝试很接近;你的语法只是一个角色。尝试以下XPath:

//div[@id='container']/li[@class='list']

您可以看到div节点和li节点之间有空格,那里应该有正斜杠。

答案 1 :(得分:1)

SimpleHTMLDOM使用CSS选择器,而不是Xpath。 CSS选择器中的任何内容也可以使用Xpath完成。 DOMXpath :: query()仅支持返回节点列表的Xpath表达式,但Xpath也可以返回标量。

在Xpath中/分隔位置路径的各个部分,而不是空格。它还有两个含义。位置路径开头的/使其成为绝对值(它从文档开始,而不是当前上下文节点)。第二个/是后代轴的短语法。

尝试:

$html = '
<div id="container">
    <li class="list">
        Test text
    </li>
</div>';

$dom = new \DomDocument;
$dom->loadHTML($html);
$xpath = new \DomXPath($dom);

echo trim($xpath->evaluate("string(//div[@id='container']//li[@class='list'])"));

输出:

Test text

在CSS选择器序列中,空间是两个选择器的组合器。

  • CSS:foo bar
  • Xpath短语法://foo//bar
  • Xpath完整语法:/descendant::foo/descendant::bar

另一个组合子对于一个孩子来说是>。此轴是Xpath中的默认轴。

  • CSS:foo > bar
  • Xpath短语法://foo/bar
  • Xpath完整语法:/descendant::foo/child::bar