给出如下的XML文档:
<root>
<foo>
<bar>a</bar>
<bar>b</bar>
<bar>c</bar>
</foo>
...
</root>
如何检索具有foo
个子节点且具有特定值的所有bar
个节点?
例如,如果我需要所有foo
- 具有bar
的元素 - 具有值a
和c
的子元素,我目前正在使用此表达式:
//*/foo[bar/text()='a'][bar/text()='c']
这很好,但如果我有更多的“bar
- 约束”它会变得笨拙,而且我不太喜欢以编程方式生成的XPath表达式:)。我正在寻找的是这些方面的东西(显然无效的语法):
//*/foo[bar/text() in-set('a', 'c')]
有什么想法吗?
答案 0 :(得分:1)
答案 1 :(得分:1)
目前还不完全清楚你是否想要AND或OR。带有两个过滤器的XPath示例是AND(即要求foo
同时包含“a”和“c”),但对其他回复的注释似乎暗示您实际上想要一个OR(任何foo
带有“a”或“c”)。使用XPath 2.0,后者非常简单:
//foo[bar[. = ('a', 'c')]]
AND有点棘手:
//foo[count(distinct-values(data(bar[. = ('a', 'c')])))) = 2]
或者,如果您要使用变量(我将展示XQuery语法,但实际上您应该使用XPath实现API为外部变量提供值):
let $values := ('a', 'c')
return //foo[count(distinct-values(data(bar[. = $values])))) = count($values)]
答案 2 :(得分:0)
如果您可以访问XPath 2.0,则可以使用matches
function:
//foo[fn:matches(bar, "a|c")]
不幸的是XPath 2.0并没有被广泛支持。
Tomalak的回答给了我一个想法:
//foo[bar[fn:matches(text(),"a|c")]]
这可能有用,因为它不是在节点集上工作,而是在单个文本节点上工作。
答案 3 :(得分:0)
对于“AND”表达,你或多或少地坚持你现在拥有的东西。虽然我把它写成:
//*/foo[bar/text()='a' and bar/text()='c']
对于“OR”表达式(您的问题尚不清楚),您可以尝试:
//*/foo[bar[contains(',a,c,', concat(',', text(), ','))]]
或者,更可读的是:
//*/foo[ bar[ contains( ',a,c,', concat(',', text(), ',') ) ] ]
这会找到<foo>
元素,这些元素包含自身符合某个规则的<bar>
个元素。规则是:“文本值(用逗号括起来)包含在搜索字符串中(用逗号括起来)”。
对于'a'
的文字值和'a,b'
的搜索字符串,您需要在',a,'
内查找',a,b,'
。因此,如果任何内部<bar>
元素匹配,则将选择外部<foo>
元素。
显然,你必须选择一个不能包含在值中的分隔符。从您的示例代码中,我选择','
,但任何有效字符都可以。
答案 4 :(得分:0)
您可以偷偷摸摸地为它添加一个元素,如:
<values>
<value>a</value>
<value>c</value>
</values>
然后这个XPath
/root/foo[count(bar[.=/root/values/value]) = count(/root/values/value)]
将找到所有foo
个元素,其中值在您的值列表中的bar
子元素的数量等于该列表中的值的数量。这将起作用 - 如果所有bar
元素都包含不同的值。