首页 文章

XPath - 属性通配符不返回具有名为value的属性的元素

提问于
浏览
4

我正在尝试使用XPath(Java)来获取所有未知节点,这些节点基于以特定值开头的未知属性 . 由于某种原因,它不返回包含名为 value 的属性的节点 . 我也在www.freeformatter.com/xpath-tester.html测试并得到了相同的结果 . 这是我有的:

XML:

<div>
    <object data="/v1/assets/mp4Video-1" type="video/mp4">
        <param name="webmSource" value="/v1/assets/webmVideo-1" type="REF"/>
    </object>
</div>

XPath Expression:

//*[starts-with(@*, '/v1/assets/')]

Results - 返回 <object> ,但不返回 <param> .

现在,如果我将XPath表达式更改为 //*[starts-with(@*, '/v1/assets/') or starts-with(@value, '/v1/assets/')] ,它将按预期返回 .

我想我的问题是, value 属性是什么导致XPath无法正确识别它作为属性,或者当 value 属性包含我要查询的值时不返回该元素?

2 回答

  • 3

    您的原始路径表达式的原因:

    //*[starts-with(@*, '/v1/assets/')]
    

    不起作用与XPath 1.0中的函数如何处理比预期更多的节点有关 . starts-with() 函数需要将单个节点作为其第一个参数,并将字符串(或计算为字符串的节点)作为其第二个参数 .

    但是在上面的表达式中, starts-with() 被赋予一组属性节点 @* 作为其第一个参数 . 在这种情况下,此函数仅使用这些属性节点中的第一个 . 集合中的所有其他节点都将被忽略 . 由于属性的顺序未在XML中定义,因此XPath引擎可以自由选择要在函数中使用的任何属性节点 . 但是您的特定XPath引擎(以及许多其他引擎)似乎始终按照其外观的顺序使用第一个属性节点 .

    为了说明这一点(并证明它),请将输入文档更改为

    <div>
        <object data="other" type="/v1/assets/mp4Video-1">
            <param name="/v1/assets/webmVideo-1" value="other" type="REF"/>
        </object>
    </div>
    

    如您所见,我更改了属性的顺序,包含 /v1/assets/ 的属性现在是 object 元素的第二个属性,反之亦然 param 元素 . 使用此输入文档,原始XPath表达式将仅返回 param 元素 .

    同样,这种行为在不同的XPath引擎之间不一定是一致的!使用XPath的其他实现可能会产生不同的结果 .


    执行所需操作的XPath表达式

    //*[@*[starts-with(., '/v1/assets/')]]
    

    用简单的英语说,它说

    选择文档中任何位置的元素,但仅当元素的所有属性节点中都有一个值以“/ v1 / assets /”开头的属性时 .

  • 2

    尝试

    //@*[starts-with(., '/v1/assets/')]
    

    返回所有属性

    //*[@*[starts-with(., '/v1/assets/')]]
    

    返回所有元素

    这将搜索所有节点的所有属性 .

相关问题