【问题标题】:Getting child nodes using xpath?使用 xpath 获取子节点?
【发布时间】:2013-02-21 11:55:05
【问题描述】:

我有以下 xml。我需要使用 xpath 查询获取根节点的所有子节点。如何编写 xpath 表达式?

<rootElement> 

  <rootElementOne xmlns="http://some.com"> 
    <rootElementTwo> 
      <Id>12345</balId> 
      <name>Name1</businessName> 
     </rootElementTwo> 
  </rootElementOne> 

  <rootElementOne xmlns="http://some.com"> 
    <rootElementTwo> 
      <Id>6789</balId> 
      <name>Name2</businessName> 
     </rootElementTwo> 
  </rootElementOne>  

</rootElement>

表达式应返回以下结果:

      <rootElementOne xmlns="http://some.com"> 
        <rootElementTwo> 
          <Id>12345</balId> 
          <name>Name1</businessName> 
         </rootElementTwo> 
      </rootElementOne> 

      <rootElementOne xmlns="http://some.com"> 
        <rootElementTwo> 
          <Id>6789</balId> 
          <name>Name2</businessName> 
         </rootElementTwo> 
      </rootElementOne>

我尝试使用rootElement/rootElementOne/*,但没有结果。

谢谢!

【问题讨论】:

  • 你试过/rootElement/rootElementOne吗?
  • @beny23:注意&lt;rootElementOne&gt; 上的默认命名空间声明。

标签: java xml xpath


【解决方案1】:

注意此处的术语。在 XML 中,至少在 XPath 术语中,“根节点”是文档中所有元素、文本节点、cmets、处理指令和其他节点的(不可见的)祖先。根节点由 XPath 表达式/ 寻址。它不是一个元素,而是最外层元素的父元素,也就是文档元素。在您的 XML 文档中,根节点是 &lt;rootElement&gt; 的父节点。

此 XPath 表达式将选择所有“根节点的子节点”:

/node()

但这会返回一个元素,即&lt;rootElement&gt;,这不是您想要的结果。

相反,您可能想要 文档元素 的所有子节点,所以这是您的 XPath 表达式:

/*/node()

这将返回 &lt;rootElementOne&gt; 元素,以及(取决于您的设置)它们之间的文本节点,其中包含空格。

或者,也许您想要文档元素的所有 element 子元素。换句话说,您不关心文本节点、cmets 或除元素之外的任何东西。 (很多不熟悉 XML 细节的人在说“元素节点”时会说“节点”。)

如果这是你想要的,它的 XPath 表达式是

/*/*

或者在你的情况下,你可以这样做

/rootElement/some:rootElementOne

其中some 在XPath 之外被声明为http://some.com 的命名空间前缀。如果您想知道如何在 Java 中为 XPath 声明名称空间前缀,请告诉我们,并向我们展示您已经在使用哪些 Java 代码来调用 XPath。或者更好的是,在这个网站上搜索,因为示例代码已经有了很好的答案。

当您尝试rootElement/rootElementOne/* 时,由于命名空间,您没有选择任何内容。 rootElementOne(在 XPath 1.0 中)形式的 XPath 步骤表示“没有命名空间中名为 rootElementOne 的元素”。 (在 XPath 2.0 中,它的意思是“在默认的 XPath 命名空间中”,并且在 XPath 之外还有其他方法可以设置默认的 XPath 命名空间。)所以您要求在无命名空间中使用 rootElementOne,而您的 &lt;rootElementOne&gt; 元素在http://some.com 命名空间。

如果您想与命名空间无关,您可以使用* 而不是rootElementOne,或者您可以使用*[local-name() = 'rootElementOne']。但是,如果您这样做是因为您不知道如何在 XML 和 XPath 中使用名称空间,那么在您学习之前,它们可能会继续成为您的肉中刺。 :-)

一旦修复,您应该得到两个&lt;some:rootElementTwo&gt; 元素(因为您要求rootElementOne 的子元素),但这仅适用于文档根节点的上下文。这是因为以元素名称 X 开头的 XPath 表达式实际上是以 child::X 开头的,这意味着上下文节点的子节点。如果您当时不知道上下文节点是什么,或者不想依赖它,请使用/// 开始您的XPath 表达式。这告诉 XPath 从文档的根节点开始。

【讨论】:

  • 在 /*/node() 与 /*/* 的部分中,您的意思是前者比后者获得更多信息?谢谢
  • @JasonAngel 是的,如上所述,/*/node() 可以返回文本节点以及元素节点。 /*/* 只会返回元素节点。
【解决方案2】:

/rootElement/* 将返回所有rootElementOne,您可以在其中执行一些操作

/rootElement//* 将返回 rootElement 以下的所有内容

【讨论】:

  • 小修正:/rootElement//* 将选择所有属于rootElement 后代的元素。它不会选择文本节点等。
猜你喜欢
  • 2015-03-30
  • 2012-09-17
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多