如何找到嵌套在两个不同标签中的两个同名节点的位置?

发布于 2024-11-07 10:41:12 字数 761 浏览 1 评论 0原文

我有以下 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 种不同的工作,分别由两个不同的“John”完成。

我使用 XPath 表达式

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

java 中的 XPath 有没有办法使用 count 或其他一些函数来执行此操作?

I have the following 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>

If I want to get the jobs of people with name="John" XPath returns all four jobs belonging to one "John". I want 2+2 different jobs done by two different "John"s each.

I use the XPath expression

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

Is there a way in XPath in java using count or some other function to do this??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独孤求败 2024-11-14 10:41:12

XPath(仅)是 XML 文档的查询语言——XPath 表达式的评估结果永远不会是修改的节点——XPath 本身不会更改任何节点的结构和/或内容。

您想要返回的是修改后的 元素,仅包含其 子元素,而仅使用 XPath 无法实现这一点。

最接近您想要的结果是

/*/employee[name='John']/jobs

这选择以下内容

    <jobs>
        <job>Writer</job>
        <job>Artist</job>
    </jobs>
    <jobs>
        <job>Engineer</job>
        <job>Editor</job>
    </jobs>

我猜您想要的结果可以通过此 XSLT 转换绝对轻松地生成 strong>:

<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>

XPath is (only) a query language for XML documents -- the result of evaluation an XPath expression is never a modified node -- XPath alone doesn't change the structure and/or contents of any node.

What you want returned is modified <employee> elements with only their <jobs> child and this cannot be achieved with XPath alone.

The closest to what you want is:

/*/employee[name='John']/jobs

This selects the following:

    <jobs>
        <job>Writer</job>
        <job>Artist</job>
    </jobs>
    <jobs>
        <job>Engineer</job>
        <job>Editor</job>
    </jobs>

What I guess is the result wanted by you can be produced absolutely easy with this XSLT transformation:

<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>

when this transformation is applied to the provided XML document:

<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>

the wanted, correct result is produced:

<name>John</name>
<jobs>
   <job>Writer</job>
   <job>Artist</job>
</jobs>
<name>John</name>
<jobs>
   <job>Engineer</job>
   <job>Editor</job>
</jobs>
琉璃梦幻 2024-11-14 10:41:12

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

XPath is always going to return a flat list, no matter where the nodes are found, which is why you simply get 4 pieces of text. If you want to group them by their parent nodes, you need to first search for the Johns and with those results, do a nested loop - for each John, do an XPath for the jobs, starting at that node. How you wish to group them in Java is up to you - perhaps a Map of String (name) to List of String (job).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文