开发者

What am I doing wrong with XPath?

开发者 https://www.devze.com 2023-01-12 21:35 出处:网络
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 name

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).g开发者_运维百科etNodeName());

}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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号