选择多个标记的 XPath

鉴于这种简化的数据格式:

<a>
<b>
<c>C1</c>
<d>D1</d>
<e>E1</e>
<f>don't select this one</f>
</b>
<b>
<c>C2</c>
<d>D2</d>
<e>E1</e>
<g>don't select me</g>
</b>
<c>not this one</c>
<d>nor this one</d>
<e>definitely not this one</e>
</a>

你将如何选择所有的 CDEB元素的子元素?

基本上是这样的:

a/b/(c|d|e)

在我自己的情况下,导致选择这些 CDE节点的查询实际上非常复杂,所以我想避免这样做:

a/b/c|a/b/d|a/b/e

这可能吗?

173751 次浏览

您可以使用属性测试来避免重复:

a/b/*[local-name()='c' or local-name()='d' or local-name()='e']

与 Dimitre 的对立观点相反,上面是在真空中的 没错,OP 没有指定与名称空间的交互。self::轴是名称空间限制的,而 local-name()不是。如果 OP 的意图是捕获 c|d|e而不考虑名称空间(考虑到问题的 OR 性质,我建议这甚至是一个可能的场景) ,那么它是“另一个仍然有一些积极票数的答案”,这是不正确的。

没有定义你就不能确定,尽管我很乐意删除我的回答,因为如果 OP 澄清了他的问题,我是不正确的。

不确定这是否有帮助,但是对于 XSL,我可以这样做:

<xsl:for-each select="a/b">
<xsl:value-of select="c"/>
<xsl:value-of select="d"/>
<xsl:value-of select="e"/>
</xsl:for-each>

这个 XPath 会不会选择 B 节点的所有子节点:

a/b/*

一个正确的答案是:

/a/b/*[self::c or self::d or self::e]

请注意

a/b/*[local-name()='c' or local-name()='d' or local-name()='e']

这个 XPath 表达式将选择以下节点:

OhMy:c


NotWanted:d


QuiteDifferent:e

为什么不用 a/b/(c|d|e)呢? 我刚刚试用了 Saxon XML 库(用一些 Clojure 优点很好地包装起来) ,它似乎可以工作。 abc.xml是 OP 所描述的文档。

(require '[saxon :as xml])
(def abc-doc (xml/compile-xml (slurp "abc.xml")))
(xml/query "a/b/(c|d|e)" abc-doc)
=> (#<XdmNode <c>C1</c>>
#<XdmNode <d>D1</d>>
#<XdmNode <e>E1</e>>
#<XdmNode <c>C2</c>>
#<XdmNode <d>D2</d>>
#<XdmNode <e>E1</e>>)