简体   繁体   中英

What am I doing wrong with XPath?

I am trying to manipulate xsd schema as an xml document that should not be a problem, I believe. But facing troubles with XPath. Whatever XPath I try, it returns nothing. Tried it with or without namespaces but no success. Please help me understand what am I doing wrong?

My xml is:

<?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>

and application code is:

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();
}

Set a namespace context using XPath.setNamespaceContext(). This binds the xs prefix to the http://www.w3.org/2001/XMLSchema namespace.

Made changes to your code. It works:

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();
        }
    }

}

The reason is that you haven't specified what xs means. An xml parser must know the namespace url, xs is just an identifier.

You can demonstrate this yourself by using the following code:

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);

You can see that I now use the identifier t instead of xs but that doesn't matter as long as you use the same namespace url.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM