如何使命名空间与开箱即用的XP​​ath一起使用?

时间:2018-01-04 11:45:30

标签: java xml xpath namespaces

对于给定的XML和XPath,在线XPath测试程序的工作方式类似于我的代码(不匹配任何内容):http://www.xpathtester.com/xpath

import java.io.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;

class test {

    public static void main(String[] args) throws Exception {

        XPathExpression expr = XPathFactory.newInstance().newXPath().compile(
            "/A[namespace-uri() = 'some-namespace']");  // This does not select anything, replacing A with * does 

        // This XPath selects as expected (in all parsers mentioned): /*[namespace-uri() = 'some-namespace']

        String xml = "<A xmlns=\"some-namespace\"> </A>";

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        Document doc = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
        NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);

        System.out.println("Number of nodes selected: " + nodes.getLength());

        for (int i = 0; i < nodes.getLength(); i++) {
            System.out.println("Node name: " + nodes.item(i).getNodeName());        
        }
    }
}

Link to Ideone

无论文档工厂是否支持名称空间,上述代码都不会选择任何内容。

这是根据XPath标准吗?或实施的细微差别?

This资源提及以下内容:

  

实际上,当XML文档使用默认命名空间时,XPath   表达式必须使用前缀,即使目标文档没有。

为了验证这一点,我更改了XPath以包含这样的前缀: /p:A[namespace-uri() = 'some-namespace'] 并添加了一个命名空间解析程序,它返回URI some-namespace ,用于前缀 p 并且有效


问题:

1)有没有办法让没有前缀的XPath表达式适用于具有默认命名空间的文档?

2)[第二个XPath测试人员] [3]如何工作? (该测试仪不符合标准)

注意:在我的应用程序中,我无法控制收到的文档和XPath。但两者都保证有效。

1 个答案:

答案 0 :(得分:1)

Freeformatter.com XPath异常

对于您的示例XML,

<root>
    <A xmlns="some-namespace"> </A>
    <A xmlns="some-namespace2"> </A>
</root>

这个XPath,

//A

应该选择 ,但在Freeformatter.com上,它会选择

<A xmlns="some-namespace2"> </A>

错误

因此,全面停止,不要使用 Freeformatter.com 。不要试图解决这个问题 - 只是不要使用该服务,因为不能信任它以一致的方式评估XPath。

一般的XPath名称空间

  

1)有没有办法让没有前缀的XPath表达式适用于具有默认命名空间的文档?

你可以

  1. 通过local-name() [不推荐]
  2. 击败名称空间
  3. 通过local-name()namespace-uri() [确定,但详细]或
  4. 来表彰名称空间
  5. 通过托管语言库的各种机制定义名称空间前缀[首选,但每个XPath托管系统不同]
  6. 有关详细信息,包括如何在许多不同托管语言中定义名称空间前缀的示例,请参阅 How does XPath deal with XML namespaces?

    对于给定的,固定的XPath可以选择忽略命名空间吗?

      

    在我的应用程序中,我无法控制我收到的文档和XPath(它保证有效)。所以我必须处理发送给我的XPath。我猜测我的问题的答案是不会的。?

    如果您正在询问是否有//A从上面的示例XML中选择节点并且仍然符合XPath的方法,那么答案确实是 no < /强>