2012-07-25 45 views
6

我有以下XML文件:Java的DOM解析器報告錯號子節點

<?xml version="1.0" encoding="UTF-8"?> 
<users> 
<user id="0" firstname="John"/> 
</users> 

於是我試圖用java解析它,但getchildnodes報告錯誤數量的子節點。

Java代碼:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder builder = factory.newDocumentBuilder(); 
Document document = builder.parse(this.file); 
document.getDocumentElement().normalize(); 
Element root = document.getDocumentElement(); 
NodeList nodes = root.getChildNodes(); 
System.out.println(nodes.getLength()); 

結果:3

而且我得到的NPE用於訪問節點的屬性,所以我猜的東西是怎麼回事可怕的錯誤。

回答

3

有三個子節點:

  • 含有換行符
  • 元素節點(標記的用戶)文本節點
  • 含有換行符
文本節點

所以當處理子節點時,檢查元素節點。

+4

謝謝,你知道一種方法來以通用的方式過濾掉元素嗎? – 2012-07-25 12:27:18

4

子節點由空白的元素和文本節點組成。在處理屬性之前,您需要檢查節點類型。您可能還需要考慮使用在JDK/JRE中可用的API的javax.xml.xpath開始的Java SE 5

例1

這個例子演示瞭如何發出針對DOM的XPath語句。

package forum11649396; 

import java.io.StringReader; 
import javax.xml.parsers.*; 
import javax.xml.xpath.*; 
import org.w3c.dom.*; 
import org.xml.sax.InputSource; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     String xml = "<?xml version='1.0' encoding='UTF-8'?><users><user id='0' firstname='John'/></users>"; 

     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     Document document = db.parse(new InputSource(new StringReader(xml))); 

     XPathFactory xpf = XPathFactory.newInstance(); 
     XPath xpath = xpf.newXPath(); 
     Element userElement = (Element) xpath.evaluate("https://stackoverflow.com/users/user", document, XPathConstants.NODE); 
     System.out.println(userElement.getAttribute("id")); 
     System.out.println(userElement.getAttribute("firstname")); 
    } 

} 

例2

下面的例子演示瞭如何發出對一個InputSource的XPath語句來獲得DOM節點。這使您不必將自己的XML解析爲DOM。

package forum11649396; 

import java.io.StringReader; 
import javax.xml.xpath.*; 
import org.w3c.dom.*; 
import org.xml.sax.InputSource; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     String xml = "<?xml version='1.0' encoding='UTF-8'?><users><user id='0' firstname='John'/></users>"; 

     XPathFactory xpf = XPathFactory.newInstance(); 
     XPath xpath = xpf.newXPath(); 
     InputSource inputSource = new InputSource(new StringReader(xml)); 
     Element userElement = (Element) xpath.evaluate("https://stackoverflow.com/users/user", inputSource, XPathConstants.NODE); 
     System.out.println(userElement.getAttribute("id")); 
     System.out.println(userElement.getAttribute("firstname")); 
    } 

} 
1

你必須確保你說明節點之間的'\ n',這個節點計算文本節點。您可以測試,使用if(root.getNodeType() == Node.ELEMENT_NODE)

 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     Document document = builder.parse(this.file); 
     document.getDocumentElement().normalize(); 
     for(Node root = document.getFirstChild(); root != null; root = root.getNextSibling()) { 
      if(root.getNodeType() == Node.ELEMENT_NODE) { 
       NodeList nodes = root.getChildNodes(); 
       System.out.println(root.getNodeName() + " has "+nodes.getLength()+" children"); 
       for(int i=0; i<nodes.getLength(); i++) { 
        Node n = nodes.item(i); 
        System.out.println("\t"+n.getNodeName()); 
       } 
      } 
     } 
0

我沒有看到任何答案解決您的最後一個音符約NPE上試圖訪問屬性時。

此外,我正在獲取NPE訪問節點屬性,所以我猜測事情會發生可怕的錯誤。

因爲我已經看到了幾個網站下面的建議,我想這是訪問屬性的常用方法:

String myPropValue = node.getAttributes().getNamedItem("myProp").getNodeValue(); 

如果節點總是包含一個myProp屬性,它工作正常,但如果它沒有屬性,getAttributes將返回null。另外,如果有屬性,但沒有myProp屬性,getNamedItem將返回空值。

我目前使用

public static String getStrAttr(Node node, String key) { 
    if (node.hasAttributes()) { 
     Node item = node.getAttributes().getNamedItem(key); 
     if (item != null) { 
      return item.getNodeValue(); 
     } 
    } 

    return null; 
} 

public static int getIntAttr(Node node, String key) { 
    if (node.hasAttributes()) { 
     Node item = node.getAttributes().getNamedItem(key); 
     if (item != null) { 
      return Integer.parseInt(item.getNodeValue()); 
     } 
    } 

    return -1; 
} 

在一個工具類,但您的里程可能會有所不同。