【问题标题】:Why is this Basic XPath Selector Not Working为什么这个基本 XPath 选择器不起作用
【发布时间】:2014-03-07 20:47:07
【问题描述】:

这是我的基本结构:

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

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

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

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

知道为什么 XPath 会表现得如此奇怪吗?在处理 DOMXPath 查询时,我看到了很多不一致的行为。

【问题讨论】:

  • 您可能遇到命名空间问题。检查您的结构中是否提到了默认命名空间(类似于 xmlns="...")
  • 你能展示更多你的 HTML 结构吗?你从哪里得到它?

标签: php dom xpath domdocument


【解决方案1】:

发生这种情况的一种方法是,如果您有一个 XHTML 文档(在根 html 元素上带有 xmlns 声明)并且您将其解析为 XML。在这样的文档中,所有元素都是 http://www.w3.org/1999/xhtml 命名空间的一部分,您需要在查询时指定这一点。

您的第一个查询 //*[@id="PrimaryContentBlock"] 将找到具有匹配 id 属性的 any 元素,包括 XHTML 命名空间中的元素(这就是 * 的含义)。第二个查询//*[@id="PrimaryContentBlock"]/form 正在寻找form 元素,这些元素在任何命名空间中不是。这与文档不匹配,因为所有 form 元素都在默认的 XHTML 命名空间中。

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

$domdocument->loadXML(...);

改成使用loadHTML:

$domdocument->loadHTML(...);

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

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

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

【讨论】:

  • 试试这个//*[@id="PrimaryContentBlock"]/*[local-name()='form']。如果它有效,那么这是一个命名空间问题。
  • 感谢 matt 和 lwburk 提​​供的命名空间技巧。我怀疑命名空间可能是我遇到的一些不一致的原因。当前的错误是由于我自己的疏忽造成的。我为前一个文档构建了一个初始 XPath 对象,但没有为我尝试查询的新文档的 DOM 重置 XPath。
【解决方案2】:

鉴于您具有上述结构,并且您确定文档格式正确,您的两个查询将工作:

$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 专业知识,要么您的输入数据格式不正确。当我对某个查询有问题时,这两个原因中至少有一个适用于我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 2021-05-14
    相关资源
    最近更新 更多