【问题标题】:xpath doesn't match if the item has one or more child elements如果项目具有一个或多个子元素,则 xpath 不匹配
【发布时间】:2015-11-02 03:53:40
【问题描述】:

我有一个看起来像这样的方法:

function braces(DOMElement $node){
    $path   = $node->getNodePath();
    $xpath = new DOMXPath($node->ownerDocument);
    $nodes = $xpath->query($path . '[*=(contains(., "{{") and contains(., "}}"))]');

    var_dump($nodes);
}

我创建了以下两个测试用例:

测试用例 1

$dom = new DOMDocument();
$dom->loadHTML('<div data-id="{{cat}}">
    <a href="http://google.com">Google</a>
</div>',LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);

braces($dom->documentElement);

这个上的var_dump()没有找到{{}}的属性。

这是测试用例 1 的结果输出:

object(DOMNodeList)#4 (1) {
  ["length"]=>
  int(0)
}

测试用例 2

$dom = new DOMDocument();
$dom->loadHTML('<div data-id="{{cat}}"></div>',LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);

braces($dom->documentElement);

当删除子a 元素时,var_dump() 现在可以找到带有{{}} 的属性。

这是测试用例 2 的结果输出:

object(DOMNodeList)#3 (1) {
  ["length"]=>
  int(1)
}

所以,我的问题是为什么当项目有孩子时它不能找到价值?

【问题讨论】:

    标签: php xpath


    【解决方案1】:

    再看看你的谓词

    *=(contains(., "{{") and contains(., "}}"))
    

    这是两个操作数的相等比较。右边的操作数是一个布尔值(A 和 B 总是布尔值)。因此,XPath 1.0 也强制左侧操作数为布尔值。 "*" 选择上下文节点的子节点; boolean(*) 如果该节点集非空,即如果上下文节点有一个或多个子节点,则为真。

    因此,如果 (a) 节点有子节点且包含大括号,或者 (b) 节点没有子节点且不包含大括号,则您的相等比较为真。

    这里的包含是什么意思?如果节点的字符串值包含'x' 作为子字符串,则表达式contains(., 'x') 为真。节点的字符串值来自该节点的子/后代;它不考虑属性。因为它忽略了属性,所以你的contains() 测试在两种情况下都是假的,所以只有当左侧操作数也为假时,谓词作为一个整体才为真,也就是说,如果节点没有子节点。

    【讨论】:

    • 在多次阅读您的答案后,它开始变得有些意义,但这是我想出的……这看起来像一个更好的查询吗? @.=(contains(., "{{") and contains(., "}}")) 经测试,似乎可以工作...
    • 不,完全是垃圾。你只是在猜测,不是吗?拿一本参考书读一读,你不会靠猜测得到正确的。
    • 并非如此。根据您所说,关于星号,我使用了“@”。表示属性
    • (a) @ 后面必须跟一个节点测试。 . 不是节点测试。任何 XPath 参考都会告诉您这一点。节点测试通常是属性名称或通配符 (*)。 (b) 您仍在尝试使用 = 运算符将节点与布尔值进行比较。你想要一个谓词:类似*[contains(@id, '{{')]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    相关资源
    最近更新 更多