XML的封裝與解析

原文

爲什麼會有本章的出現?因爲XML實在是太重要了,而且被廣泛應用!不論是數據存儲,還是其他方面,如配置文件等。XML是一種對獨立於任何編程語言的數據進行編碼的機制。在數據交換領域,正在變得非常流行!因爲他的基於節點的存儲格式特點,以致於有很多適合的場合,可用它來描述。當然Java也爲打包和解析XML文件做了很好的支撐!本章系Java之美[從菜鳥到高手演變]系列之XML的打包與解析,學完本章,你會基本掌握XML的大部分操作!

在閱讀過程中有任何問題,請及時聯繫:egg。

郵箱:[email protected] 微博:http://weibo.com/xtfggef

轉載請說明出處:http://blog.csdn.net/zhangerqing

一、XML語言的特點

1、XML獨立於任何編程語言,允許人們按接收者容易解析的方式,對複雜數據進行編碼。先來看一個簡單的XML格式的文件:

[html] view plaincopy
  1. <note>  
  2. <to>George</to>  
  3. <from>John</from>  
  4. <heading>Reminder</heading>  
  5. <body>Don't forget the meeting!</body>  
  6. </note>  

對於程序員來說,很容易讀懂這是什麼意思,很明顯這是傳遞給他人的一個便籤,如果我們寫出下面這樣:

George

John

Reminder

Don't forget the meeting!

雖然最終從XML中提取出來就是上面的內容,但是我們從上面的內容根本看不出這是什麼。

2、數據做成XML有助於改變其內容

如果我們現在想再添加一項:時間。在XML中我們可以這樣:

[html] view plaincopy
  1. <note>  
  2. <to>George</to>  
  3. <from>John</from>  
  4. <heading>Reminder</heading>  
  5. <body>Don't forget the meeting!</body>  
  6. <time>2012-12-03</time>  
  7. </note>  

在我們解析的時候,只要從對應的標籤“time”找就行,非常方便!這樣的特點,有助於組織複雜的數據。

3、XML 與 HTML 的主要差異

XML 不是 HTML 的替代,XML 和 HTML 爲不同的目的而設計,XML 被設計爲傳輸和存儲數據,其焦點是數據的內容。HTML 被設計用來顯示數據,其焦點是數據的外觀。HTML 旨在顯示信息,而 XML 旨在傳輸信息。HTML的標記不是所有的都需要成對出現,XML則要求所有的標記必須成對出現,HTML標記不區分大小寫,XML則 大小敏感,即區分大小寫。

4、XML 文檔是一種樹結構

上圖表示下面的 XML 中的一本書:

[html] view plaincopy
  1. <bookstore>  
  2. <book category="COOKING">  
  3.   <title lang="en">Everyday Italian</title>   
  4.   <author>Giada De Laurentiis</author>   
  5.   <year>2005</year>   
  6.   <price>30.00</price>   
  7. </book>  
  8. <book category="CHILDREN">  
  9.   <title lang="en">Harry Potter</title>   
  10.   <author>J K. Rowling</author>   
  11.   <year>2005</year>   
  12.   <price>29.99</price>   
  13. </book>  
  14. <book category="WEB">  
  15.   <title lang="en">Learning XML</title>   
  16.   <author>Erik T. Ray</author>   
  17.   <year>2003</year>   
  18.   <price>39.95</price>   
  19. </book>  
  20. </bookstore>  

二、XML的解析技術

1、大名鼎鼎的DOM技術

說它大名鼎鼎可是一點不爲過,DOM 是 W3C 處理 XML 的標準 API,它是許多其它與 XML 處理相關的標準的基礎,不僅是 Java,其它諸如JavaScriptPHP,MS .NET 等等語言都實現了該標準, 成爲了應用最爲廣泛的 XML 處理方式。當然,爲了能提供更多更加強大的功能,Java 對於 DOM 直接擴展工具類有很多,比如很多 Java 程序員耳熟能詳的 JDOM,DOM4J 等等, 它們基本上屬於對 DOM 接口功能的擴充,保留了很多 DOM API 的特性,許多原本的 DOM 程序員甚至都沒有任何障礙就熟練掌握了另外兩者的使用,直觀、易於操作的方式使它深受廣大 Java 程序員的喜愛。

2、綠色環保的 SAX

SAX 的應運而生有它特殊的需要,爲什麼說它綠色環保呢,這是因爲 SAX 使用了最少的系統資源和最快速的解析方式對 XML 處理提供了支持。 但隨之而來繁瑣的查找方式也給廣大程序員帶來許多困擾,常常令人頭痛不已,同時它對 XPath 查詢功能的支持,令人們對它又愛又恨。

二種技術的比較:

DOM

優缺點:實現 W3C 標準,有多種編程語言支持這種解析方式,並且這種方法本身操作上簡單快捷,十分易於初學者掌握。其處理方式是將 XML 整個作爲類似樹結構的方式讀入內存中以便操作及解析,因此支持應用程序對 XML 數據的內容和結構進行修改,但是同時由於其需要在處理開始時將整個 XML 文件讀入到內存中去進行分析,因此其在解析大數據量的 XML 文件時會遇到類似於內存泄露以及程序崩潰的風險,請對這點多加註意。

適用範圍:小型 XML 文件解析、需要全解析或者大部分解析 XML、需要修改 XML 樹內容以生成自己的對象模型

SAX

SAX 從根本上解決了 DOM 在解析 XML 文檔時產生的佔用大量資源的問題。其實現是通過類似於流解析的技術,通讀整個 XML 文檔樹,通過事件處理器來響應程序員對於 XML 數據解析的需求。由於其不需要將整個 XML 文檔讀入內存當中,它對系統資源的節省是十分顯而易見的,它在一些需要處理大型 XML 文檔以及性能要求較高的場合有起了十分重要的作用。支持 XPath 查詢的 SAX 使得開發人員更加靈活,處理起 XML 來更加的得心應手。但是同時,其仍然有一些不足之處也困擾廣大的開發人員:首先是它十分複雜的 API 接口令人望而生畏,其次由於其是屬於類似流解析的文件掃描方式,因此不支持應用程序對於 XML 樹內容結構等的修改,可能會有不便之處。

適用範圍:大型 XML 文件解析、只需要部分解析或者只想取得部分 XML 樹內容、有 XPath 查詢需求、有自己生成特定 XML 樹對象模型的需求

三、實例運用
首先造一個xml文檔出來:(books.xml放在項目根路徑下,不是src)

[html] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2.  <books>   
  3.    <book id="01" name="book1">   
  4.       <title>Harry Potter</title>   
  5.       <author>J K. Rowling</author>   
  6.    </book>   
  7.    <book id="02" name="book2">  
  8.       <title>Thinking in Java</title>  
  9.       <author>Bruke</author>  
  10.    </book>   
  11.  </books>   
使用DOM進行解析

[java] view plaincopy
  1. /** 
  2.  * the DOM Parser Example 
  3.  * @author egg  
  4.  * email:[email protected]  
  5.  * microblog:http://weibo.com/xtfggef 
  6.  */  
  7. public class DOMTest {  
  8.   
  9.     /* build a DocumentBuilderFactory */  
  10.     DocumentBuilderFactory builderFactory = DocumentBuilderFactory  
  11.             .newInstance();  
  12.   
  13.     public static void main(String[] args) {  
  14.         DOMTest parser = new DOMTest();  
  15.         Document document = parser.parse("books.xml");  
  16.         /* get root element */  
  17.         Element rootElement = document.getDocumentElement();  
  18.   
  19.         /* get all the nodes whose name is book */  
  20.         NodeList nodeList = rootElement.getElementsByTagName("book");  
  21.         if (nodeList != null) {  
  22.             for (int i = 0; i < nodeList.getLength(); i++) {  
  23.                 /* get every node */  
  24.                 Node node = nodeList.item(i);  
  25.                 /* get the next lever's ChildNodes */  
  26.                 NodeList nodeList2 = node.getChildNodes();  
  27.                 for (int j = 0; j < nodeList2.getLength(); j++) {  
  28.                     Node node2 = nodeList2.item(j);  
  29.                     if (node2.hasChildNodes()) {  
  30.                         System.out.println(node2.getNodeName() + ":"  
  31.                                 + node2.getFirstChild().getNodeValue());  
  32.                     }  
  33.                 }  
  34.             }  
  35.         }  
  36.     }  
  37.   
  38.     /* Load and parse XML file into DOM */  
  39.     public Document parse(String filePath) {  
  40.         Document document = null;  
  41.         try {  
  42.             /* DOM parser instance */  
  43.             DocumentBuilder builder = builderFactory.newDocumentBuilder();  
  44.             /* parse an XML file into a DOM tree */  
  45.             document = builder.parse(new File(filePath));  
  46.         } catch (ParserConfigurationException e) {  
  47.             e.printStackTrace();  
  48.         } catch (SAXException e) {  
  49.             e.printStackTrace();  
  50.         } catch (IOException e) {  
  51.             e.printStackTrace();  
  52.         }  
  53.         return document;  
  54.     }  
  55. }  
輸出:

title:Harry Potter
author:J K. Rowling
title:Thinking in Java
author:Bruke

想弄懂xml的解析,需要先清楚幾個概念:節點、屬性,如下圖:


這樣結合上面的例子就容易理解了,給一個例子,大家自己去練習下:

[html] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2.  <books>   
  3.    <name>Think in C++</name>  
  4.    <price>100</price>  
  5.    <author>brucl</author>  
  6.  </books>   

使用SAX進行解析:

[java] view plaincopy
  1. public class SAXTest {  
  2.   
  3.     class BookHandler extends DefaultHandler {  
  4.         private List<String> nameList;  
  5.         private boolean title = false;  
  6.   
  7.         public List<String> getNameList() {  
  8.             return nameList;  
  9.         }  
  10.   
  11.         // Called at start of an XML document  
  12.         @Override  
  13.         public void startDocument() throws SAXException {  
  14.             System.out.println("Start parsing document...");  
  15.             nameList = new ArrayList<String>();  
  16.         }  
  17.   
  18.         // Called at end of an XML document  
  19.         @Override  
  20.         public void endDocument() throws SAXException {  
  21.             System.out.println("End");  
  22.         }  
  23.   
  24.         @Override  
  25.         public void startElement(String uri, String localName, String qName,  
  26.                 Attributes atts) throws SAXException {  
  27.             // Using qualified name because we are not using xmlns prefixes  
  28.             // here.  
  29.             if (qName.equals("title")) {  
  30.                 title = true;  
  31.             }  
  32.         }  
  33.   
  34.         @Override  
  35.         public void endElement(String namespaceURI, String localName,  
  36.                 String qName) throws SAXException {  
  37.             // End of processing current element  
  38.             if (title) {  
  39.                 title = false;  
  40.             }  
  41.         }  
  42.   
  43.         @Override  
  44.         public void characters(char[] ch, int start, int length) {  
  45.             // Processing character data inside an element  
  46.             if (title) {  
  47.                 String bookTitle = new String(ch, start, length);  
  48.                 System.out.println("Book title: " + bookTitle);  
  49.                 nameList.add(bookTitle);  
  50.             }  
  51.         }  
  52.   
  53.     }  
  54.   
  55.     public static void main(String[] args) throws SAXException, IOException {  
  56.         XMLReader parser = XMLReaderFactory.createXMLReader();  
  57.         BookHandler bookHandler = (new SAXTest()).new BookHandler();  
  58.         parser.setContentHandler(bookHandler);  
  59.         parser.parse("books.xml");  
  60.         System.out.println(bookHandler.getNameList());  
  61.     }  
  62. }  

XML的打包

[java] view plaincopy
  1. public class SAXGeneratorXml {  
  2.     public static void main(String[] args) {  
  3.         String outputPath = "persons.xml";  
  4.         generateXml(outputPath);  
  5.     }  
  6.   
  7.     public static void generateXml(String outputPath) {  
  8.         try {  
  9.             Person[] arr = new Person[] { new Person("egg"22),  
  10.                     new Person("niu"21) };  
  11.             List<Person> list = Arrays.asList(arr);// 將數組轉換成List  
  12.             Document doc = generateXml(list);// 生成XML文件  
  13.             outputXml(doc, outputPath);// 將文件輸出到指定的路徑  
  14.         } catch (Exception e) {  
  15.             System.err.println("出現異常");  
  16.         }  
  17.     }  
  18.   
  19.     /** 
  20.      * 將XML文件輸出到指定的路徑 
  21.      * @param doc 
  22.      * @param fileName 
  23.      * @throws Exception 
  24.      */  
  25.     private static void outputXml(Document doc, String fileName)  
  26.             throws Exception {  
  27.         TransformerFactory tf = TransformerFactory.newInstance();  
  28.         Transformer transformer = tf.newTransformer();  
  29.         DOMSource source = new DOMSource(doc);  
  30.         transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");  
  31.         transformer.setOutputProperty(OutputKeys.INDENT, "yes");// 設置文檔的換行與縮進  
  32.         PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));  
  33.         StreamResult result = new StreamResult(pw);  
  34.         transformer.transform(source, result);  
  35.         System.out.println("生成XML文件成功!");  
  36.     }  
  37.   
  38.     /** 
  39.      * 生成XML文件 
  40.      * @param list 
  41.      * @return 
  42.      */  
  43.     public static Document generateXml(List<Person> list) {  
  44.         Document doc = null;  
  45.         Element root = null;  
  46.         try {  
  47.             DocumentBuilderFactory factory = DocumentBuilderFactory  
  48.                     .newInstance();  
  49.             DocumentBuilder builder = factory.newDocumentBuilder();  
  50.             doc = builder.newDocument();  
  51.             root = doc.createElement("person");  
  52.             doc.appendChild(root);  
  53.         } catch (Exception e) {  
  54.             e.printStackTrace();  
  55.             return null;// 如果出現異常,則不再往下執行  
  56.         }  
  57.   
  58.         int len = list.size();  
  59.         Element element;  
  60.         for (int i = 0; i < len; i++) {  
  61.             Person person = list.get(i);  
  62.             element = doc.createElement("person" + (i + 1));  
  63.             element.setAttribute("age""" + person.getAge());  
  64.             element.setAttribute("name", person.getName());  
  65.             root.appendChild(element);  
  66.         }  
  67.         return doc;  
  68.     }  
  69. }  
發佈了11 篇原創文章 · 獲贊 6 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章