XPath возвращает ноль для "узла", когда isNameSpaceAware и isValidating "истина" - PullRequest
7 голосов
/ 20 июля 2011

Я получаю нулевой узел, когда пытаюсь проанализировать файл XML.

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

Я сталкиваюсь с этой проблемой только в случае -
1. DocumentBuilderFactory - setNameSpaceAware - это правда
2. DocumentBuilderFactory - setValidating имеет значение true.

Если для них установлено значение false, то я получаю правильные результаты. Может кто-нибудь помочь мне понять, каково отношение установки этих атрибутов к ложным? (Я проверил этот вопрос, но мои сомнения не прояснились)

Вот это 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>

Ответы [ 2 ]

4 голосов
/ 20 июля 2011

Самое быстрое решение - не делать setNamespaceAware(true); :-) Однако, если вы хотите использовать XPath с пространством имен, вы наткнулись на классическую проблему - XPath: есть ли способ установить пространство имен по умолчанию для запросов ? , в этом XPath не поддерживает концепцию пространства имен по умолчанию .

Таким образом, ваш XPath должен использовать префикс пространства имен, чтобы запрос мог найти какие-либо узлы. Однако вы можете установить NamespaceContext в экземпляре XPath , чтобы преобразовать префикс пространства имен или пространство имен по умолчанию в 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.

0 голосов
/ 20 июля 2011

XML поддерживает пространство имен. Каждый элемент XML (и атрибут) имеет ассоциированное пространство имен; если не указано иное, это пустое (по умолчанию) пространство имен.

В вашем случае вполне вероятно, что XML-документ, который вы пытаетесь прочитать, использует пространства имен, а ваш запрос XPath, похоже, только запрашивает пространство имен emtpy. Поэтому вы не получите результат обратно. Убедитесь, что вы используете правильное пространство имен, и оно будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...