我无法让following-sibling
轴工作。
我有一个XML文档如下。我试过像name(/T/p/q/following-sibling::*[1]
这样的东西。我知道name
只会产生第一个集合,但是,该表达式不会返回任何内容。我在Ubuntu上使用xmlstarlet
命令尝试XPath。
<T>
<p><q>
<a1>A</a1>
<a2>A</a2>
<a3>A</a3>
<a4>A</a4>
<a5><b1>A</b1></a5>
</q></p>
</T>
给定输入为/T/p/q
,我想要所有子元素节点的名称,但仅限于该级别。也就是说,输出应该是
a1
a2
a3
a4
a5
答案 0 :(得分:2)
在XPath 1.0中,通过评估单个 XPath表达式,无法获得所需的子元素名称/T/p/q/*
。
因此,需要在第一步中选择所有元素:
/T/p/q/*
然后,对于生成的XmlNodeList中包含的每个元素,从该元素求值的新XPath表达式将生成其名称。
使用XPath 1.0的不同托管语言,可以实现此算法的不同实现。
下面是一个示例,其中XPath 1.0的托管语言是XSLT 1.0 :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:variable name="vWanted" select="/T/p/q/*"/>
<xsl:for-each select="$vWanted">
<xsl:value-of select="name()"/> <xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<T>
<p><q>
<a1>A</a1>
<a2>A</a2>
<a3>A</a3>
<a4>A</a4>
<a5><b1>A</b1></a5>
</q></p>
</T>
执行算法的两个步骤并生成所需结果:
a1 a2 a3 a4 a5
<强> II。单个XPath 2.0表达式 - 解决方案:
/T/p/q/*/name()
对上述XPath 2.0表达式的评估会生成一个包含五个项目的序列,每个项目都是不同/T/p/q/*
元素的名称。
答案 1 :(得分:1)
实际上,它比你想象的要简单得多。
/T/p/q/*
返回a1, a2, a3, a4, a5
。
它会选择q
的所有子女,这是p
的孩子,T
的孩子是context node
的孩子。
通过说“孩子”,我的意思是“直系孩子”。不是“后代”。因此,它只会选择a1-a5
级别的节点。
正如您所说,name()
函数仅返回节点集中第一个节点的名称。我想你必须遍历节点集才能将所有名称作为单个字符串。
使用xmlstarlet
,您可以执行此操作:
xml sel -t -m "/T/p/q/*" -v "name(.)" -n input.xml
它匹配节点集,在其中的每个节点上调用name(.)
并在之后打印换行符。
-m
以匹配XPath表达式-v
打印XPath表达式返回的值-n
换新行要使用following-sibling
轴,您必须处于同一级别,例如选择a2
的所有后续兄弟,您将使用/T/p/q/a2/following-sibling::*
。这将返回a3, a4, a5
。