我有以下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/*
但没有结果。
谢谢!
答案 0 :(得分:5)
请注意这里的术语。在XML中,至少在XPath术语中,“根节点”是文档中所有元素,文本节点,注释,处理指令和其他节点的(不可见)祖先。根节点由XPath表达式/
寻址。它不是元素,而是最外层元素的父元素,a.k.a。文档元素。在XML文档中,根节点是<rootElement>
的父节点。
此根XPath表达式将选择所有“根节点的子节点”:
/node()
但是会返回一个元素,即<rootElement>
,这不是你想要的结果。
相反,你可能想要文档元素的所有子节点,所以这是你的XPath表达式:
/*/node()
这将返回<rootElementOne>
个元素,以及(取决于您的设置)它们之间的文本节点,它由空格组成。
或者,也许您想要文档元素的所有元素子元素。换句话说,除了元素之外,您不关心文本节点,注释或任何其他内容。 (许多不熟悉XML细节的人在表示“元素节点”时会说“节点”。)
如果这是你想要的,那么它的XPath表达式是
/*/*
或者在你的情况下,你可以做
/rootElement/some:rootElementOne
其中some
在XPath之外声明为http://some.com
的命名空间前缀。如果您想知道如何在Java中声明XPath的名称空间前缀,请告诉我们,并向我们展示您已经使用的用于调用XPath的Java代码。或者更好的是,在这个网站上搜索,因为示例代码已经有了很好的答案。
当您尝试rootElement/rootElementOne/*
时,由于命名空间,您没有选择任何内容。形式为rootElementOne
的XPath步骤(在XPath 1.0中)意味着“没有命名空间中名为rootElementOne的元素”。 (在XPath 2.0中,它表示“在默认的XPath命名空间中”,并且XPath之外还有一些方法可以设置默认的XPath名称空间。)所以你要求rootElementOne
没有命名空间,而你的<rootElementOne>
元素位于http://some.com
命名空间中。
如果您希望与名称空间无关,则可以使用*
代替rootElementOne
,或者使用*[local-name() = 'rootElementOne']
。但是,如果你这样做是因为你不知道如何在XML和XPath中使用命名空间,那么在你学习之前,它们可能会继续成为你肉体的刺。 : - )
修复后,您应该获得两个<some:rootElementTwo>
元素(因为您要求rootElementOne
的子元素),但这只能在文档根节点的上下文中使用。这是因为以元素名称X
开头的XPath表达式实际上是以child::X
开头的,这意味着上下文节点的子节点。如果您当时不知道上下文节点是什么,或者不想依赖它,请使用/
或//
启动XPath表达式。这告诉XPath从文档的根节点开始。
答案 1 :(得分:2)
/rootElement/*
将返回您可以在
rootElementOne
/rootElement//*
将返回rootElement