DOM解析XML


一、DOM方式的解析原理

DOM模式解析XML,是把整個XML文檔當成一個對象來處理,會先把整個文檔讀入到內存里。是基於樹的結構,通常需要加載整文檔和構造DOM樹,然后才能開始工作。

 

 

二、優缺點及適用情況

優點:a、由於整棵樹在內存中,因此可以對xml文檔隨機訪問b、可以對xml文檔進行修改操作c、較sax,dom使用也更簡單。

缺點:a、整個文檔必須一次性解析完a、由於整個文檔都需要載入內存,對於大文檔成本高

 

 

三、注意的問題

 

四、其他

 

五、程序源代碼和XML源文檔

1、源代碼

  1 import java.io.File;  
  2 import java.io.IOException;  
  3   
  4 import javax.xml.parsers.DocumentBuilder;  
  5 import javax.xml.parsers.DocumentBuilderFactory;  
  6 import javax.xml.parsers.ParserConfigurationException;  
  7   
  8 import org.w3c.dom.Document;  
  9 import org.w3c.dom.Element;  
 10 import org.w3c.dom.NamedNodeMap;  
 11 import org.w3c.dom.Node;  
 12 import org.w3c.dom.NodeList;  
 13 import org.xml.sax.SAXException;  
 14   
 15 public class DoXmlWithDOM {  
 16   
 17     public static void main(String[] args) {  
 18         File file = new File("F:/demo.xml");  
 19         (new DoXmlWithDOM()).readXML(file);  
 20     }  
 21   
 22     /* 
 23      * 讀取XML(文檔對象-根元素節點-所有的Element類型節點-Text類型節點的內容) ; 
 24      * 獲取文檔對象:DocumentBuilderFactory → DocumentBuilder → Document 
 25      */  
 26     public void readXML(File file) {  
 27         // ❶Ⅰ獲得DocumentBuilderFactory  
 28         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
 29         try {  
 30             // ❷Ⅱ獲得DocumentBuilder  
 31             DocumentBuilder builder = factory.newDocumentBuilder();  
 32             // ❸Ⅲ--獲得文檔對象--  
 33             Document doc = builder.parse(file);  
 34             // ❹Ⅳ獲得根元素  
 35             Element element = doc.getDocumentElement();  
 36             // ❺Ⅴ用方法遍歷遞歸打印根元素下面所有的ElementNode(包括屬性,TextNode非空的值),用空格分層次顯示.  
 37             listAllChildNodes(element, 0);// 參數0表示設定根節點層次為0,它的前面不打印空格.  
 38         } catch (ParserConfigurationException e) {  
 39             e.printStackTrace();  
 40         } catch (SAXException e) {  
 41             e.printStackTrace();  
 42         } catch (IOException e) {  
 43             e.printStackTrace();  
 44         }  
 45     }  
 46   
 47     /* 
 48      * 遞歸遍歷並打印所有的ElementNode(包括節點的屬性和文本節點的有效內容),按一般的xml樣式展示出來(空格來表示層次) 
 49      */  
 50     public void listAllChildNodes(Node node, int level) {  
 51         // 只處理ElementNode類型的節點,感覺這種類型的節點(還有有效的文本節點)才是真正有用的數據,其他注釋節點,空白節點等都用不上.  
 52         if (node.getNodeType() == Node.ELEMENT_NODE) {  
 53             boolean hasTextChild = false;// 變量表示該節點的第一個子節點是否就是一個有有效內容的文本節點)  
 54             // Ⅰ❶【打印 - 空格】空格的長度 - level(n級ElementNode有n個長度的空格在前面)  
 55             String levelSpace = "";  
 56             for (int i = 0; i < level; i++) {  
 57                 levelSpace += "    ";  
 58             }  
 59             // Ⅱ❷【打印 - 開始標簽】先打印ElementNode的開始標簽(有屬性的話也要打印)  
 60             System.out.print(levelSpace + "<" + node.getNodeName()  
 61                     + (node.hasAttributes() ? " " : ">"));// 有屬性的話節點的開始標簽后面的尖括號">"就留待屬性打印完再打印  
 62             // Ⅲ❸【打印 - 屬性】遍歷打印節點的所有屬性  
 63             if (node.hasAttributes()) {  
 64                 NamedNodeMap nnmap = node.getAttributes();  
 65                 for (int i = 0; i < nnmap.getLength(); i++) {  
 66                     System.out.print(nnmap.item(i).getNodeName()  
 67                             + "=\""// 字符串里含雙引號要用到轉義字符\  
 68                             + nnmap.item(i).getNodeValue() + "\""  
 69                             + (i == (nnmap.getLength() - 1) ? "" : " "));// 不是最后一個屬性的話屬性之間要留空隙  
 70                 }  
 71                 System.out.print(">");// 開始標簽里的屬性全部打印完加上尖括號">"  
 72             }  
 73             // Ⅳ❹【打印 - 子節點】該ElementNode包含子節點時候的處理  
 74             if (node.hasChildNodes()) {  
 75                 level++;// 有下一級子節點,層次加1,新的層次表示的是這個子節點的層次(遞歸調用時傳給了它)  
 76                 // 獲得所有的子節點列表  
 77                 NodeList nodelist = node.getChildNodes();  
 78                 // 循環遍歷取到所有的子節點  
 79                 for (int i = 0; i < nodelist.getLength(); i++) {  
 80                     // Ⅳ❹❶【有效文本子節點】子節點為TextNode類型,並且包含的文本內容有效  
 81                     if (nodelist.item(i).getNodeType() == Node.TEXT_NODE  
 82                             && (!nodelist.item(i).getTextContent()  
 83                                     .matches("\\s+"))) {// 用正則選取內容包含非空格的有效字符的文本節點  
 84                         hasTextChild = true;// 該ElementNode的一級子節點是存在有效字符的文本節點  
 85                         System.out.print(nodelist.item(i).getTextContent());// 在開始標簽后面添加文本內容  
 86                         // Ⅳ❹❷【ElementNode子節點】子節點是正常的ElementNode的處理  
 87                     } else if (nodelist.item(i).getNodeType() == Node.ELEMENT_NODE) {  
 88                         System.out.println();  
 89                         // 遞歸調用方法 - 以遍歷該節點下面所有的子節點  
 90                         listAllChildNodes(nodelist.item(i), level);// level表示該節點處於第幾個層次(相應空格)  
 91                     }  
 92                 }  
 93                 level--;// 遍歷完所有的子節點,層次變量隨子節點的層數,依次遞減,回歸到該節點本身的層次  
 94                 // level++ 和 level--對於該節點的子節點影響的是子節點的初值  
 95             }  
 96             // Ⅴ❺【打印 - 結束標簽】打印元素的結束標簽.如果它的第一個一級子節點是有效文本的話,文本和結束標簽添加到開始標簽后面,  
 97             // 層次什么的就作廢用不上了,否則,才按層次打印結束標簽.  
 98             System.out.print(((hasTextChild) ? "" : "\n" + levelSpace) + "</"  
 99                     + node.getNodeName() + ">");  
100         }  
101     }  
102   
103 }

2、xml文檔

 1 <?xml version="1.0" encoding="UTF-8"?>  
 2   
 3 <employees bb="bbbbb" yy="yyyyy">  
 4       
 5     <!--An XML Note -->  
 6       
 7     <?target text?>  
 8       
 9     <employee id="11" name="xiaowang">  
10           
11         <sex>man</sex>  
12           
13         <age>25</age>  
14       
15     </employee>  
16       
17     <employee id="12" name="liyi">  
18           
19         <sex>woman</sex>  
20           
21         <age>45</age>  
22       
23     </employee>  
24   
25 </employees>

六、解析效果圖

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM