2010-08-25 69 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(); 
     } 
    } 

}