我尝试解析看起来像的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-强调我的):


  使用以下命令将节点测试中的QName扩展为扩展名:
  表达式上下文中的名称空间声明。这是一样的
  起始标签和结束标签中元素类型名称的扩展方式
  除了不使用通过xmlns声明的默认名称空间:if
  QName没有前缀,则名称空间URI为null(此
  与属性名称的扩展方式相同)。如果
  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中的名称空间。仅仅因为您的文档中没有前缀并不意味着就没有名称空间。

阅读Javadoc for compile(...)

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

10-10 11:45