所以我试图使用XPath(1.0)来获取某个类型的所有元素,其本身或任何祖先都具有特定的参数值。诀窍是参数可以是值列表,所以我不能只查找@parameter =' value'。这是我案例的文档示例,让我们说我正在寻找外部参照,他们或他们的任何祖先都有平台=" mobile":
<doc>
<block>
<xref platform="mobile desktop">1</xref>
</block>
<block platform="mobile">
<xref platform="desktop">2</xref>
</block>
<block platform="desktop">
<xref platform="mobile">3</xref>
</block>
</doc>
我(在一些帮助下)提出了以下几乎可以实现的XPath:
//xref[contains(concat(' ', normalize-space(ancestor-or-self::*/@platform), ' '), ' mobile ')]
目标是让concat同时连接外部参照和祖先的所有平台值,然后查看移动设备是否在那里。所以在示例文档中它应该返回所有3个外部参照,但它不会,它会省略第3个外部参照。我认为祖先或自我从根级别开始评估,所以一旦找到一个不是移动的平台,它就会失败,而不会实际检查其余的祖先或自我。再加上这种行为,concat并没有真正做任何事情,因为它只是一次查看一个节点的平台值。
有谁知道如何解决这个特殊情况?
答案 0 :(得分:1)
下面的xpath
//xref[contains( @platform, 'mobile' )] | //xref/ancestor::*[contains( @platform, 'mobile' )]/xref
给了我:
<xref platform="mobile desktop">1</xref>
<xref platform="desktop">2</xref>
<xref platform="mobile">3</xref>
答案 1 :(得分:1)
我猜你可能正在使用XPath 1.0(你真的应该说),因为当选择了多个属性时,normalize-space(ancestor-or-self::*/@platform)
会出错。
在XPath 1.0中,此表达式将normalize-space应用于文档顺序中节点集中的第一个节点,这意味着最外面的@platform,因为祖先在文档顺序中位于其后代之前。如果您想要最里面的@platform,请使用normalize-space((ancestor-or-self::*/@platform)[last()])
。
但如果您选择的元素中任何祖先都有一个包含“mobile”的@platform作为子字符串,那就是
//xref[ancestor::*/@platform[contains(., 'mobile')]]
答案 2 :(得分:1)
在XPath 1.0中,像normalize-space()
这样的字符串函数需要一个字符串参数,当给定一个节点集时,它只会计算集合中的第一个节点。因此,以下表达式仅评估第一个找到的platform
属性:
normalize-space(ancestor-or-self::*/@platform)
为了避免上述问题,OP的尝试XPath可以稍微调整一下如下:
//xref[
ancestor-or-self::*[
contains(concat(' ', normalize-space(@platform), ' '), ' mobile ')
]
]
演示: xpathtester
,xpatheval
这样,字符串函数就会应用于各个platform
元素的ancestor-or-self
属性。