【问题标题】:How to find the location of two nodes of the same name nested in two different tags?如何找到嵌套在两个不同标签中的两个同名节点的位置?
【发布时间】:2011-05-12 11:29:28
【问题描述】:

我有以下 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" 的人的工作,XPath 会返回属于一个“John”的所有四个工作。我希望两个不同的“约翰”分别完成 2+2 个不同的工作。

我使用 XPath 表达式

"//employees/employee[name='John']/jobs/job/text()"

在 java 中的 XPath 中有没有一种方法可以使用 count 或其他一些函数来做到这一点?

【问题讨论】:

  • @@Niranjani S:能否请您编辑您的问题并指定您想要获得的确切结果——列出您想要获得的确切 XML 节点。

标签: java xml xslt xpath


【解决方案1】:

XPath (仅)是一种用于 XML 文档的查询语言 -- XPath 表达式的求值结果绝不是修改过的节点 -- XPath 本身不会改变结构和/或内容任何节点。

您想要返回的是修改后的 &lt;employee&gt; 元素,只有它们的 &lt;jobs&gt; 子元素,这不能仅使用 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>

【讨论】:

  • @Niranjani S:不要感到内疚——只是跳上马车兜风。你不会后悔的:)
【解决方案2】:

XPath 总是会返回一个平面列表,无论在哪里找到节点,这就是为什么你只得到 4 段文本的原因。如果要按父节点对它们进行分组,则需要首先搜索 John,然后根据这些结果执行嵌套循环 - 对于每个 John,从该节点开始为作业执行 XPath。您希望如何在 Java 中对它们进行分组取决于您 - 可能是字符串(名称)到字符串列表(作业)的映射。

【讨论】:

  • 获取名为“John”的员工节点,然后使用 getChildNodes() 遍历员工节点即可!
猜你喜欢
  • 2020-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多