【问题标题】:XPath returning null for "Node" when isNameSpaceAware and isValidating are "true"当 isNameSpaceAware 和 isValidating 为“true”时,XPath 为“Node”返回 null
【发布时间】:2011-07-20 10:18:11
【问题描述】:

当我尝试解析 XML 文件时,我得到一个空节点。

XPath xPath = XPathFactory.newInstance().newXPath();
    Node node = null;
    try {
        node = (Node) xPath.evaluate(
                "/mynode",
                doc,
                XPathConstants.NODE);

我只在以防万一的情况下遇到这个问题-
1. DocumentBuilderFactory-setNameSpaceAware 为真
2. DocumentBuilderFactory-setValidating 为真。

如果这些设置为 false,那么我会得到正确的结果。谁能帮助我理解将这些属性设置为 false 的关系是什么? (我已经检查了this的问题,但它并没有清除我的疑问)

这里是xml-

<?xml version="1.0" encoding="UTF-8"?>
<mynode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.example.com" xsi:schemaLocation="http://www.example.com example.xsd">
    <name>TargetName</name>
    <desc>desc goes here</desc>
    <pack>my.this</pack>
    <object>my.ExampleObject</object>
    <properties>
        <attrib>
            <name>id</name>
            <value>ZZZ</value>
        </attrib>
        <attrib>
            <name>ind</name>
            <value>X</value>
        </attrib>
    </properties>
    <children>
        <child>
            <name>childnodename</name>
            <desc>description goes here</desc>
            <invalues>
                <scope>ALL</scope>
            </invalues>
            <outvalues>
                <scope>ALL</scope>
            </outvalues>
            <akey>
                <aname>AAA</aname>
                <key></key>
            </akey>
            <msg>
                <success>code1</success>
                <failure>code2</failure>
            </msg>
        </child>
    </children>
</mynode>

【问题讨论】:

    标签: java xpath


    【解决方案1】:

    最快的解决方法是不做setNamespaceAware(true); :-) 但是,如果您想要一个支持命名空间的 XPath,那么您偶然发现了一个经典问题 - XPath: Is there a way to set a default namespace for queries?,因为 XPath 不支持 默认命名空间

    因此,您的 XPath 必须使用名称空间前缀才能让查询找到任何节点。但是,您可以在 XPath 实例上设置 NamespaceContext 以将命名空间前缀或默认命名空间解析为 URI。一种方法,例如:

    import java.util.*;
    import java.io.ByteArrayInputStream;
    import javax.xml.namespace.NamespaceContext;
    import javax.xml.parsers.*;
    import javax.xml.xpath.*;
    import org.w3c.dom.*;
    
    public class XmlParse {
        public static void main(String[] args) throws Exception {
    
            String xml =
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<mynode xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.example.com\" xsi:schemaLocation=\"http://www.example.com example.xsd\">" +
                "<name>TargetName</name>" +
                "</mynode>";
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder builder = dbf.newDocumentBuilder();
            Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
    
            final String nonameNamespace = doc.getFirstChild().getNamespaceURI();
    
            NamespaceContext ctx = new NamespaceContext() {
                public String getNamespaceURI(String prefix) {
                    String uri = null;
                    if (prefix.equals("n")) {
                        uri = nonameNamespace;
                    }
                    return uri;
                }
    
                @Override
                public Iterator getPrefixes(String val) {
                    throw new IllegalAccessError("Not implemented!");
                }
    
                @Override
                public String getPrefix(String uri) {
                    throw new IllegalAccessError("Not implemented!");
                }
            };
    
            XPath xPath = XPathFactory.newInstance().newXPath();
            xPath.setNamespaceContext(ctx);
    
    
            Node node = null;
            try {
                node = (Node) xPath.evaluate("/n:mynode/n:name", doc, XPathConstants.NODE);
                System.out.println(node.getNodeName());
                System.out.println(node.getFirstChild().getNodeValue());
            } catch (Exception e) {
    
            }
        }
    }
    

    因此,当遇到带有 n 前缀的节点时,这会将默认命名空间 (xmlns) 解析为 http://www.example.com

    【讨论】:

      【解决方案2】:

      XML 是命名空间感知的。每个 XML 元素(和属性)都有一个关联的名称空间;如果未指定,则为空(默认)命名空间。

      在您的情况下,您尝试读取的 XML 文档很可能使用命名空间,而您的 XPath 查询似乎只查询 emtpy 命名空间。因此,您不会得到结果。确保使用正确的命名空间,它会起作用。

      【讨论】:

      • 是的。我的 XML 文件使用命名空间。但我没有得到你的第二点。抱歉,我是 XPath 相关内容的新手。您能否详细说明如何做到这一点?-“您的 XPath 查询似乎只查询 emtpy 命名空间。因此您没有得到返回结果。请确保使用正确的命名空间,它会起作用”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-22
      • 2011-05-22
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      相关资源
      最近更新 更多