我尝试解析如下所示的 xml
<EvaluateHandRequest xmlns="http://www.aaa.com/aaa/schemas">
<card>
<suit>HEARTS</suit>
<face>TEN</face>
</card>
<card>
<suit>SPADES</suit>
<face>KING</face>
</card>
<card>
<suit>HEARTS</suit>
<face>KING</face>
</card>
<card>
<suit>DIAMONDS</suit>
<face>TEN</face>
</card>
<card>
<suit>CLUBS</suit>
<face>TEN</face>
</card>
</EvaluateHandRequest>
为此,我使用 XPathExpression,但无法提取结果。
SAXBuilder jdomBuilder = new SAXBuilder();
Document jdomDocument = jdomBuilder.build(xmlSource);
Element element = jdomDocument.getRootElement();
XPathFactory xFactory = XPathFactory.instance();
XPathExpression xExpression = xFactory.compile("/*/*");
List<Element> list = xExpression.evaluate(element);
System.out.println(list.size() + " " + list.get(0).getName());//5 card
for (Element element2 : list) {
System.out.println(element2.getValue()); //proper result
}
如果我在编译期间使用 /*/*
表达式,我会得到所有卡片及其值,其中 card
位于层次结构的顶部。
但是当我使用 /*/card
时,我没有从那里获得任何元素。
如果我在表达式中写入任何节点的任何名称,我将无法提取任何结果。
我有什么问题吗?
最佳答案
XPath 表达式始终是命名空间感知的。这就是它们的指定方式(section 2.3 - 强调我的):
A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null (this is the same way attribute names are expanded). It is an error if the QName has a prefix for which there is no namespace declaration in the expression context.
因此,您需要指定要使用的命名空间......不过,在我们解决这个问题之前,让我们看看您显示的 XPath 的使用情况:
XPathExpression xExpression = xFactory.compile("/*/*"); List<Element> list = xExpression.evaluate(element);
那不应该编译...... XPathExpression 是一个泛型类型的类。您希望它返回 Elements...要正确执行此操作,您需要在compile 方法中向结果添加过滤器。考虑您当前的行:
XPathExpression xExpression = xFactory.compile("/*/*");
这应该是:
XPathExpression<Element> xExpression = xFactory.compile("/*/*", Filters.element());
这将使所有内容编译时没有任何错误或警告......
现在,要扩展 XPath 表达式以仅提取 card
元素,我们需要包含命名空间:
Namespace aaa = Namespace.getNamespace("aaa", "http://www.aaa.com/aaa/schemas");
例如,要仅获取西装元素:
Namespace aaa = Namespace.getNamespace("aaa", "http://www.aaa.com/aaa/schemas");
XPathExpression<Element> xExpression = xFactory.compile(
"/*/aaa:card/aaa:suit", Filters.element(), null, aaa);
如果需要多个命名空间,您可以添加它们。
请注意,命名空间声明使用前缀 aaa
,即使 XML 文档中没有使用前缀,您仍然需要一个前缀来引用 XPath 中的命名空间。仅仅因为文档中没有前缀并不意味着没有命名空间......
关于java - jdom2 xPathExpression拉节点失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29060789/