2011-07-20 46 views
6

當我試圖解析XML文件時,我得到一個空節點。當isNameSpaceAware和isValidating爲「true」時,XPath爲「節點」返回null

XPath xPath = XPathFactory.newInstance().newXPath(); 
    Node node = null; 
    try { 
     node = (Node) xPath.evaluate(
       "/mynode", 
       doc, 
       XPathConstants.NODE); 

我面對這個問題只在區分
1. DocumentBuilderFactory- setNameSpaceAware是真的
2. DocumentBuilderFactory-的setValidating是真實的。

如果這些設置爲false,那麼我會得到正確的結果。任何人都可以幫助我理解將這些屬性設置爲false是什麼關係? (我已經檢查this的問題,但它並不清楚我的疑問)

這裏是XML的

<?xml version="1.0" encoding="UTF-8"?> 
<mynode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.example.com" xsi:schemaLocation="http://www.example.com example.xsd"> 
    <name>TargetName</name> 
    <desc>desc goes here</desc> 
    <pack>my.this</pack> 
    <object>my.ExampleObject</object> 
    <properties> 
     <attrib> 
      <name>id</name> 
      <value>ZZZ</value> 
     </attrib> 
     <attrib> 
      <name>ind</name> 
      <value>X</value> 
     </attrib> 
    </properties> 
    <children> 
     <child> 
      <name>childnodename</name> 
      <desc>description goes here</desc> 
      <invalues> 
       <scope>ALL</scope> 
      </invalues> 
      <outvalues> 
       <scope>ALL</scope> 
      </outvalues> 
      <akey> 
       <aname>AAA</aname> 
       <key></key> 
      </akey> 
      <msg> 
       <success>code1</success> 
       <failure>code2</failure> 
      </msg> 
     </child> 
    </children> 
</mynode> 

回答

4

最快的解決方法是不行setNamespaceAware(true); :-)然而,如果你想有一個命名空間感知的XPath那麼你已經跨過的一個經典問題跌跌撞撞 - XPath: Is there a way to set a default namespace for queries?,在XPath不支持默認命名空間的概念。

因此,您的XPath必須使用命名空間前綴,以便查詢找到任何節點。但是,您可以在XPath實例上設置NamespaceContext以將名稱空間前綴或默認名稱空間解析爲URI。要做到這一點,例如一個辦法:

import java.util.*; 
import java.io.ByteArrayInputStream; 
import javax.xml.namespace.NamespaceContext; 
import javax.xml.parsers.*; 
import javax.xml.xpath.*; 
import org.w3c.dom.*; 

public class XmlParse { 
    public static void main(String[] args) throws Exception { 

     String xml = 
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + 
      "<mynode xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.example.com\" xsi:schemaLocation=\"http://www.example.com example.xsd\">" + 
      "<name>TargetName</name>" + 
      "</mynode>"; 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     dbf.setNamespaceAware(true); 
     DocumentBuilder builder = dbf.newDocumentBuilder(); 
     Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes())); 

     final String nonameNamespace = doc.getFirstChild().getNamespaceURI(); 

     NamespaceContext ctx = new NamespaceContext() { 
      public String getNamespaceURI(String prefix) { 
       String uri = null; 
       if (prefix.equals("n")) { 
        uri = nonameNamespace; 
       } 
       return uri; 
      } 

      @Override 
      public Iterator getPrefixes(String val) { 
       throw new IllegalAccessError("Not implemented!"); 
      } 

      @Override 
      public String getPrefix(String uri) { 
       throw new IllegalAccessError("Not implemented!"); 
      } 
     }; 

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


     Node node = null; 
     try { 
      node = (Node) xPath.evaluate("/n:mynode/n:name", doc, XPathConstants.NODE); 
      System.out.println(node.getNodeName()); 
      System.out.println(node.getFirstChild().getNodeValue()); 
     } catch (Exception e) { 

     } 
    } 
} 

所以遇到n前綴的節點時,這將解決默認命名空間(xmlns)到http://www.example.com

0

XML命名空間是感知。每個XML元素(和屬性)都有一個關聯的名稱空間;如果未指定,則爲空(默認)名稱空間。

就你而言,你試圖讀取的XML文檔很可能使用了命名空間,而你的XPath查詢似乎只是查詢了emtpy命名空間。因此你不會得到結果。確保使用正確的名稱空間,它將起作用。

+0

是的。我的XML文件使用一個名稱空間。但我沒有得到你的第二點。對不起,但我是XPath相關內容的新手。你能否詳細說明如何做到這一點? - 「你的XPath查詢似乎只是查詢emtpy命名空間,因此你不會得到一個結果,確保使用正確的命名空間,它將工作」 – Pramod

相關問題