首页 文章

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

提问于
浏览
1

对于给定的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, and that worked .

问题:

1)是否有一种方法可以使没有前缀的XPath表达式适用于具有默认命名空间的文档?

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

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

1 回答

  • 1

    Freeformatter.com XPath异常

    对于您的示例XML,

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

    这个XPath,

    //A
    

    should select nothing ,但在Freeformatter.com,它选择

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

    这是 WRONG .

    因此,全程停止,请勿使用 Freeformatter.com . Don 't try to work around this – simply don' t使用该服务,因为无法信任它以一致的方式评估XPath .


    一般来说

    XPath名称空间

    1)有没有一种方法可以使没有前缀的XPath表达式适用于具有默认命名空间的文档?

    您可以

    • 通过 local-name() [不推荐]击败名称空间

    • 荣誉名称空间通过 local-name()namespace-uri() [确定,但详细],或者

    • 通过托管语言库的各种机制定义名称空间前缀[首选,但每个XPath托管系统各不相同]

    有关更多详细信息,包括如何在许多不同托管语言中定义名称空间前缀的示例,请参阅 How does XPath deal with XML namespaces?


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

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

    如果你想让 //A 从上面的示例XML中选择一个节点并且仍然符合XPath,那么答案确实是 no .

相关问题