java - jdom2 xPathExpression拉节点失败

标签 java xml jdom-2

我尝试解析如下所示的 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 中的命名空间。仅仅因为文档中没有前缀并不意味着没有命名空间......

阅读Javadoc for compile(...)

关于java - jdom2 xPathExpression拉节点失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29060789/

相关文章:

c++ - 使用 PugiXML 提取嵌入在另一个 XML 中的 XML

PHP:使用 simplexml 遍历 XML 文件的所有级别

java - JDOM 2.0 中的 XPath 2.0 功能

java - 使用 JDOM 在 Java 中构建包含我的 FIX 订单的 .XML 文件

java - 使用SQLite数据库的Android用户登录系统

java - 性能说明: code runs slower after warm up

java - admob 测试广告 ID 正常工作,但真实 ID 广告在 Android Studio 中不起作用

java - Child 和 Sub Child 中的相同命名空间 (JDOM2)

java - Java 中除复数字符串的正则表达式

java - 将自定义颜色与 SXSSF (Apache POI) 结合使用