我有以下XML:
<employees>
<employee> <!--forgot to include an attribute-->
<name>John</name>
<jobs>
<job>Writer</job>
<job>Artist</job>
</jobs>
</employee>
<employee>
<name>John</name>
<jobs>
<job>Engineer</job>
<job>Editor</job>
</jobs>
</employee>
</employees>
如果我想获得姓名为“John”的人的工作,XPath将返回属于一个“John”的所有四个工作。我希望由两个不同的“约翰”各自完成2 + 2个不同的工作。
我使用XPath表达式
"//employees/employee[name='John']/jobs/job/text()"
在java中使用count或其他函数的XPath中有没有办法做到这一点?
答案 0 :(得分:2)
XPath是(仅)XML文档的查询语言 - 评估结果XPath表达式永远不是修改过的节点 - 仅XPath不会改变结构和/或内容任何节点。
您想要返回的内容是修改后的<employee>
元素,仅包含<jobs>
子元素,而单凭XPath无法实现这一点。
最接近您想要的是:
/*/employee[name='John']/jobs
选择以下:
<jobs>
<job>Writer</job>
<job>Artist</job>
</jobs>
<jobs>
<job>Engineer</job>
<job>Editor</job>
</jobs>
我猜想通过此XSLT转换可以非常轻松地生成您想要的结果:
<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:copy-of select=
"/*/employee[name='John']/node()[not(self::comment())]"/>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<employees>
<employee>
<!--forgot to include an attribute-->
<name>John</name>
<jobs>
<job>Writer</job>
<job>Artist</job>
</jobs>
</employee>
<employee>
<name>John</name>
<jobs>
<job>Engineer</job>
<job>Editor</job>
</jobs>
</employee>
</employees>
产生了想要的正确结果:
<name>John</name>
<jobs>
<job>Writer</job>
<job>Artist</job>
</jobs>
<name>John</name>
<jobs>
<job>Engineer</job>
<job>Editor</job>
</jobs>
答案 1 :(得分:0)
XPath始终会返回一个平面列表,无论找到哪个节点,这就是为什么你只需要获得4个文本。如果要按父节点对它们进行分组,则需要首先搜索Johns并使用这些结果,对每个John执行嵌套循环,从该节点开始为作业执行XPath。您希望如何使用Java对它们进行分组取决于您 - 可能是字符串(名称)到字符串列表(作业)。