jdom2 xPathExpression拉节点失败

时间:2015-03-15 12:51:05

标签: 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时,我从那里得不到任何元素。 如果我在表达式中写任何节点的任何名称,我就无法得到任何结果。 我有什么问题?

1 个答案:

答案 0 :(得分:0)

XPath表达式始终可识别名称空间。这就是它们的指定方式(section 2.3 - 强调我的):

  

使用。将节点测试中的QName扩展为扩展名   表达式上下文中的名称空间声明。这是一样的   对start和end-tags中的元素类型名称进行扩展    ,但不使用xmlns声明的默认命名空间 :if   QName没有前缀,那么 名称空间URI为空 (这个   与扩展属性名称的方式相同)。如果这是一个错误   QName有一个前缀,其中没有名称空间声明   表达背景。

因此,您需要指定要使用的命名空间....在我们解决之前,让我们看一下您显示工作的XPath的用法:

XPathExpression xExpression = xFactory.compile("/*/*");
List<Element> list  = xExpression.evaluate(element);

那不应该编译.... XPathExpression是一个泛型类。您希望它返回元素...要做到这一点,您需要在编译方法中为结果添加一个过滤器。考虑一下您当前的行:

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(...)