我在使用XPath时遇到了什么问题?

时间:2010-08-25 17:48:15

标签: java xml xpath

我相信,我试图将xsd架构作为一个xml文档来操作,这应该不是问题。但是面对XPath的麻烦。无论我尝试什么XPath,它都不会返回任何内容。尝试使用或不使用命名空间但没有成功。 请帮我理解我做错了什么?

我的xml是:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.mydomain.com" xmlns="http://www.mydomain.com" elementFormDefault="qualified">

  <xs:complexType name="Label">
    <xs:choice maxOccurs="unbounded" minOccurs="0">
      <xs:element name="Listener"/>
    </xs:choice>
  </xs:complexType>

</xs:schema>

和应用程序代码是:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setValidating(false);
domFactory.setNamespaceAware(true);
domFactory.setIgnoringComments(true);
domFactory.setIgnoringElementContentWhitespace(true);

try {
    DocumentBuilder builder = domFactory.newDocumentBuilder();
    Document dDoc = builder.parse("C:/Temp/test.xsd");

    // This part works
    Node rootNode = dDoc.getElementsByTagName("xs:schema").item(0);
    System.out.println(rootNode.getNodeName());

    // This part doesn't work
    XPath xPath1 = XPathFactory.newInstance().newXPath();
    NodeList nList1 = (NodeList) xPath1.evaluate("//xs:schema", dDoc, XPathConstants.NODESET);  
    System.out.println(nList1.item(0).getNodeName());

    // This part doesn't work
    XPath xPath2 = XPathFactory.newInstance().newXPath();
    NodeList nList2 = (NodeList) xPath2.evaluate("//xs:element", rootNode, XPathConstants.NODESET); 
    System.out.println(nList2.item(0).getNodeName());

}catch (Exception e){
    e.printStackTrace();
}

3 个答案:

答案 0 :(得分:4)

使用XPath.setNamespaceContext()设置名称空间上下文。这会将xs前缀绑定到http://www.w3.org/2001/XMLSchema命名空间。

答案 1 :(得分:3)

对您的代码进行了更改。它有效:

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XPathtest {
    public static void main(String[] args) {
        DocumentBuilderFactory domFactory = DocumentBuilderFactory
                .newInstance();
        domFactory.setValidating(false);
        domFactory.setNamespaceAware(true);
        domFactory.setIgnoringComments(true);
        domFactory.setIgnoringElementContentWhitespace(true);

        try {
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            Document dDoc = builder.parse("C:/Temp/test.xsd");

            // This part works
            Node rootNode = dDoc.getElementsByTagName("xs:schema").item(0);
            System.out.println(rootNode.getNodeName());

            // This part doesn't work
            XPath xPath1 = XPathFactory.newInstance().newXPath();

            NamespaceContext nsContext = new NamespaceContext() {

                @Override
                public String getNamespaceURI(String prefix) {
                    return "http://www.w3.org/2001/XMLSchema";
                }

                @Override
                public String getPrefix(String namespaceURI) {
                    return "xs";
                }

                @Override
                public Iterator getPrefixes(String namespaceURI) {
                    Set s = new HashSet();
                    s.add("xs");
                    return s.iterator();
                }

            };

            xPath1.setNamespaceContext((NamespaceContext) nsContext);

            NodeList nList1 = (NodeList) xPath1.evaluate("//xs:schema", dDoc,
                    XPathConstants.NODESET);
            System.out.println(nList1.item(0).getNodeName());

            // This part doesn't work
            // XPath xPath2 = XPathFactory.newInstance().newXPath();
            NodeList nList2 = (NodeList) xPath1.evaluate("//xs:element",
                    rootNode, XPathConstants.NODESET);
            System.out.println(nList2.item(0).getNodeName());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

答案 2 :(得分:2)

原因是您没有指定xs的含义。 xml解析器必须知道命名空间url,xs只是一个标识符。

您可以使用以下代码自行演示:

XPath xPath = XPathFactory.newInstance().newXPath();

SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
nsContext.addNamespace("t", "http://www.w3.org/2001/XMLSchema");
xPath.setNamespaceContext(nsContext);

xPath.evaluate("//t:schema", dDoc, XPathConstants.NODESET);

您可以看到我现在使用标识t而不是xs,但只要您使用相同的命名空间网址就无关紧要。