为什么这个基本XPath选择器不起作用

时间:2014-02-10 13:30:26

标签: php dom xpath domdocument

这是我的基本结构:

<div id="PrimaryContentBlock">
    <form>
         ......

我正在尝试从表单中选择元素,但XPath没有找到超过primarycontentblock div的任何内容。

第一个查询找到父节点,但第二个查询什么也找不到。

$dom->query('//*[@id="PrimaryContentBlock"]');
$dom->query('//*[@id="PrimaryContentBlock"]/form');

知道为什么XPath会表现得那么奇怪吗?在使用DOMXPath查询时,我一直看到很多不一致的行为。

2 个答案:

答案 0 :(得分:1)

如果你有一个XHTML文档(在根xmlns元素上有一个html decalaration)并且你正在将它解析为XML,那么可能会发生这种情况。在这样的文档中,所有元素都是http://www.w3.org/1999/xhtml命名空间的一部分,您需要在查询时指定它。

您的第一个查询//*[@id="PrimaryContentBlock"]会找到任何带有id属性的元素,包括XHTML命名空间中的那些(这就是*的含义)。第二个查询//*[@id="PrimaryContentBlock"]/form正在查找任何名称空间中form个元素。由于所有form元素都在默认的XHTML名称空间中,因此无法与文档匹配。

如果这是一个XHTML文档,最简单的解决方法是将其解析为HTML。如果您目前正在做类似的事情:

$domdocument->loadXML(...);

将其更改为使用loadHTML

$domdocument->loadHTML(...);

如果要将文档解析为XML,则需要在查询中指定命名空间。首先,您需要使用DOMXPath实例register the namespace uri and prefix you are going to use,然后更改您的查询以包含新前缀:

$xpath = new DOMXPath($doc);
$xpath->registerNamespace('xhtml', "http://www.w3.org/1999/xhtml");

$result = $xpath->query('//*[@id="PrimaryContentBlock"]/xhtml:form')

答案 1 :(得分:0)

鉴于您拥有上述结构,并且您确信文档格式正确,您的查询工作:

$xml = <<<EOF
<div id="PrimaryContentBlock">
    <form></form>
</div>
EOF;

$doc = new DOMDocument();
$doc->loadHTML($xml);
$selector = new DOMXPath($doc);

foreach($selector->query('//*[@id="PrimaryContentBlock"]/form') as $element) {
    echo $element->nodeName;
}

输出:

form

如果以下句子适合您:

  

在使用DOMXPath查询时,我一直看到很多不一致的行为。

...那么你对XPath的专业知识不够,或者你的输入数据不是很好。当我遇到某个查询问题时,至少有一个原因适用于我。