1

我尝试解析看起来像的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我没有从那里得到任何元素。如果我在表达式中写任何节点的任何名称,我将无法提取任何结果。我有什么问题?

4

1 回答 1

0

XPath 表达式始终是名称空间感知的。这就是它们的指定方式(第 2.3 节- 强调我的):

使用来自表达式上下文的命名空间声明将节点测试中的 QName 扩展为扩展名称。这与对开始和结束标记中的元素类型名称进行扩展的方式相同 ,只是不使用使用 xmlns 声明的默认命名空间:如果 QName 没有前缀,则命名空间 URI 为空(这是相同的方式属性名称被扩展)。如果 QName 具有在表达式上下文中没有名称空间声明的前缀,则这是一个错误。

因此,您需要指定要使用的命名空间......不过,在我们解决这个问题之前,让我们看看您对 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 中的名称空间。仅仅因为您的文档中没有前缀并不意味着没有命名空间......

阅读Javadoccompile(...)

于 2015-03-15T13:37:07.280 回答