2010-08-25 73 views
1

我想操纵xsd模式作为一个xml文档,我认为这不应该是一个问题。但面临XPath的麻烦。无论我尝试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(); 
} 

回答

4

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

+0

然后xPath1.evaluate(“// schema”,...)应该这样做吗? – willcodejavaforfood 2010-08-25 17:58:04

+1

@willcodejavaforfood:No.'// schema'表示没有命名空间下树中的任何'schema'元素。应该是'/ xs:schema' – 2010-08-25 18:14:18

+0

@Ajjandro - 确定这很有意义,谢谢 – willcodejavaforfood 2010-08-25 20:40:16

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但只要你使用相同的命名空间URL不要紧。

+2

您应该先导入org.custommonkey.xmlunit.SimpleNamespaceContext或类似的东西,因为JDK不包含'javax.xml的实现.namespace.Namespace'。 – 2010-10-06 13:32:19

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

}