XPath为“节点"返回null.当isNameSpaceAware和isValidating为"true"时, [英] XPath returning null for "Node" when isNameSpaceAware and isValidating are "true"

查看:53
本文介绍了XPath为“节点"返回null.当isNameSpaceAware和isValidating为"true"时,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am getting a null node when I an trying to parse an XML file.

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

我仅在情况下遇到此问题-
1. DocumentBuilderFactory- setNameSpaceAware为true
2. DocumentBuilderFactory- setValidating为true.

I am facing this issue only in case-
1. DocumentBuilderFactory- setNameSpaceAware is true
2. DocumentBuilderFactory- setValidating is true.

如果将它们设置为false,那么我得到正确的结果.谁能帮助我了解将这些属性设置为false有什么关系?(我已经检查了这个问题,但并不清楚我的疑问)

If these are set to false, then I am getting correct results. Can anyone help me on understanding what is the relation of setting these attributes to false? (I have checked this question, but it does not clear my doubt)

这是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>

推荐答案

最快的解决方法是不执行 setNamespaceAware(true); :-)但是,如果您希望使用名称空间的XPath,则可以偶然发现了一个经典问题-

The quickest fix is to not do setNamespaceAware(true); :-) However, if you want a namespace aware XPath then you have stumbled across a classic problem - XPath: Is there a way to set a default namespace for queries?, in that XPath does not support the concept of a default namespace.

因此,您的XPath必须使用名称空间前缀才能使查询找到任何节点.但是,您可以设置 NamespaceContext

So your XPath must use a namespace prefix in order for the query to find any nodes. However, you can set a NamespaceContext on the XPath instance to resolve the namespace prefix or default namespace to a URI. One way to do this, for example:

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 遇到.

So this will resolve the default namespace (xmlns) to http://www.example.com when a node with n prefix is encountered.

这篇关于XPath为“节点"返回null.当isNameSpaceAware和isValidating为"true"时,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆