鉴于这种简化的数据格式:
<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>
您将如何选择作为 B
元素的子元素的所有 C
、D
和 E
?
基本上,类似:
a/b/(c|d|e)
在我自己的情况下,不仅仅是 a/b/
,导致选择这些 C
、D
、E
节点的查询实际上非常复杂,所以我想避免这样做:
a/b/c|a/b/d|a/b/e
这可能吗?
一个正确的答案是:
/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/*[local-name()='c' or local-name()='d' or local-name()='e']
与 Dimitre 的反对意见相反,在 OP 没有指定与命名空间的交互的真空中,上述内容并非不正确。 self::
轴是名称空间限制的,local-name()
不是。如果 OP 的意图是捕获 c|d|e
而不管命名空间如何(考虑到问题的 OR 性质,我认为这甚至是一种可能的情况),那么它是“另一个仍然有一些积极投票的答案”,这是不正确的。
如果没有定义,你就无法确定,但如果 OP 澄清了他的问题以至于我不正确,我很乐意将我的答案删除为真正不正确。
local-name()
,这是否意味着它会匹配任何命名空间的标签?如果我使用 self::
,它必须匹配什么命名空间?我如何只匹配 OhMy:c
?
为什么不a/b/(c|d|e)
?我刚刚尝试使用 Saxon XML library (用一些 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>>)
不确定这是否有帮助,但使用 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/*
不定期副业成功案例分享
or
是一个逻辑运算符——它对两个布尔值进行运算。 XPath union 运算符|
在两组节点上运行。这些是完全不同的,并且每个都有特定的用例。使用|
可以解决原始问题,但它会导致理解 XPath 表达式的时间更长、更复杂且更具挑战性。此答案中更简单的表达式使用or
运算符生成所需的节点集,并且 可以 在<xsl:for-each>
XSLT 操作的“选择”属性中指定。去尝试一下。local-name()
才是正确的,而不管元素所在的命名空间。这是一种非常罕见的情况 - 通常人们确实关心以下之间的差异:{2 } 和sql:table
,或在architecture:column
、sql:column
、array:column
、military:column
之间