【问题标题】:How to make namespaces work with XPaths out of the box?如何使命名空间开箱即用地与 XPath 一起使用?
【发布时间】:2018-06-14 03:26:47
【问题描述】:

对于给定的 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'] 并添加了一个命名空间解析器,它为前缀 p 返回 URI some-namespace并且有效


问题:

1) 有没有一种方法可以使不带前缀的 XPath 表达式在具有默认命名空间的文档上工作?

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

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

【问题讨论】:

    标签: java xml xpath namespaces


    【解决方案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. 通过local-name()namespace-uri() 尊重命名空间[好的,但是很冗长],或者
    3. 通过托管语言库的各种机制定义命名空间前缀 [首选但因 XPath 托管系统而异]

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


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

    在我的应用程序中,我无法控制收到的文档和 XPath(保证有效)。所以我必须使用发送给我的任何 XPath。我猜我的问题的答案是否定的。?

    如果您问是否有办法让//A 从上述示例 XML 中选择一个节点并且仍然符合 XPath,那么答案确实是

    【讨论】:

    • 是的,我认为这一定是错误的。对我的其他问题有什么想法吗?
    • 答案已更新以解决您在 XPath 问题中更一般的命名空间。
    • 在我的应用程序中,我无法控制收到的文档和 XPath(保证有效)。所以我必须使用发送给我的任何 XPath。我猜我的问题的答案是否定的。?
    • 回答再次更新以解决您关于在不更改 XPath 的情况下忽略命名空间的更具体问题。
    • 我在问是否有办法让 /A[namespace-uri() = 'some-namespace'] 从示例 XML 中选择一个节点。由于这不包含前缀
    猜你喜欢
    • 2014-10-13
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    • 2011-02-01
    • 2012-01-11
    • 2016-09-14
    • 2021-08-26
    • 1970-01-01
    相关资源
    最近更新 更多