Java高級特性 第14節 解析XML文檔(2) - SAX 技術
阿新 • • 發佈:2019-04-27
rim ride brush books 適合 函數實現 jdk 特性 自定義類
一、SAX解析XML文檔
SAX的全稱是Simple APIs for XML,也即XML簡單應用程序接口。與DOM不同,SAX提供的訪問模式是一種順序模式,這是一種快速讀寫XML數據的方式。當使用SAX分析器對XML文檔進行分析時,會觸發一系列事件,並激活相應的事件處理函數,應用程序通過這些事件處理函數實現對XML文檔的訪問,因而SAX接口也被稱作事件驅動接口。
1. SAX解析原理:
加載一點,讀取一點,處理一點。對內存要求比較低。
SAX解析工具內置在jdk中:org.xml.sax.*
2. SAX解析工具核心:
核心的API:
- SAXParser類:
- parse(File f, DefaultHandler dh)方法: 解析xml文件
- 參數一: File:表示 讀取的xml文件
- 參數二: DefaultHandler: SAX事件處理程序。使用DefaultHandler的子類
3. 解析步驟:
- 第一步:創建對象
1)創建SAXParser對象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
2)調用parse方法
/*** 參數一: xml文檔 * 參數二: DefaultHandler的子類 MyDefaultHandler()為自定義 */ parser.parse(new File(".\\src\\Go\\person.xml"), new MyDefaultHandler());
註意: 這裏創建SAXParser對象 不能直接通過構造函數來創造,因為用到了單例工廠模式。
DefaultHandler類的API:後三個最重要
-
- void startDocument() : 在讀到文檔開始時調用void endDocument() :在讀到文檔結束時調用
- void startElement(String uri, String localName, String qName, Attributes attributes) : 讀到開始標簽時調用
- void endElement(String uri, String localName, String qName) :讀到結束標簽時調用
- void characters(char[] ch, int start, int length) : 讀到文本內容時調用
- 第二步:自定義類繼承DefaultHandler重寫方法
這些都是要重寫的,舉個例子:
public class MyDefaultHandler extends DefaultHandler { /** * 開始文檔時調用 */ @Override public void startDocument() throws SAXException { System.out.println("MyDefaultHandler.startDocument()"); } /** * 開始標簽時調用 * @param qName: 表示開始標簽的標簽名 * @param attributes: 表示開始標簽內包含的屬性列表 */ @Override public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException { System.out.println("MyDefaultHandler.startElement()-->"+qName); } /** * 結束標簽時調用 * @param qName: 結束標簽的標簽名稱 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("MyDefaultHandler.endElement()-->"+qName); } /** * 讀到文本內容的時調用 * @param ch: 表示當前讀完的所有文本內容 * @param start: 表示當前文本內容的開始位置 * @param length: 表示當前文本內容的長度 * char[]( 張三 20) 100 * 98 2 */ @Override public void characters(char[] ch, int start, int length) throws SAXException { //得到當前文本內容 String content = new String(ch,start,length); System.out.println("MyDefaultHandler.characters()-->"+content); } /** * 結束文檔時調用 */ @Override public void endDocument() throws SAXException { System.out.println("MyDefaultHandler.endDocument()"); } }
xml文件:
<?xml version="1.0" encoding="utf-8"?> <contactList> <contact id="001" name="eric"> <name>張三</name> <age>20</age> <phone>134222223333</phone> <email>[email protected]</email> <qq>432221111</qq> </contact> <contact id="002" name="jacky"> <name>eric</name> <age>20</age> <phone>134222225555</phone> <email>[email protected]</email> <qq>432222222</qq> </contact> </contactList>
結果:
MyDefaultHandler.startDocument()
MyDefaultHandler.startElement()-->contactList
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->contact
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->name
MyDefaultHandler.characters()-->張三
MyDefaultHandler.endElement()-->name
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->age
MyDefaultHandler.characters()-->20
MyDefaultHandler.endElement()-->age
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->phone
MyDefaultHandler.characters()-->134222223333
MyDefaultHandler.endElement()-->phone
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->email
MyDefaultHandler.characters()-->[email protected]
MyDefaultHandler.endElement()-->email
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->qq
MyDefaultHandler.characters()-->432221111
MyDefaultHandler.endElement()-->qq
MyDefaultHandler.characters()-->
MyDefaultHandler.endElement()-->contact
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->contact
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->name
MyDefaultHandler.characters()-->eric
MyDefaultHandler.endElement()-->name
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->age
MyDefaultHandler.characters()-->20
MyDefaultHandler.endElement()-->age
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->phone
MyDefaultHandler.characters()-->134222225555
MyDefaultHandler.endElement()-->phone
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->email
MyDefaultHandler.characters()-->[email protected]
MyDefaultHandler.endElement()-->email
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->qq
MyDefaultHandler.characters()-->432222222
MyDefaultHandler.endElement()-->qq
MyDefaultHandler.characters()-->
MyDefaultHandler.endElement()-->contact
MyDefaultHandler.characters()-->
MyDefaultHandler.endElement()-->contactList
MyDefaultHandler.endDocument()
註意:結果中出現MyDefaultHandler.characters()–>空白 ,是因為<contactList> <contact>之間也是有文本的,是換行和空格被characters方法讀取了。
二、DOM解析和SAX解析總結
DOM解析 | SAX解析 |
原理: 一次性加載xml文檔,不適合大容量的文件讀取 | 原理: 加載一點,讀取一點,處理一點。適合大容量文件的讀取 |
DOM解析可以任意進行增刪改成 | SAX解析只能讀 |
DOM解析任意讀取任何位置的數據,甚至往回讀 | 取SAX解析只能從上往下,按順序讀取,不能往回讀 |
DOM解析面向對象的編程方法(Node,Element,Attribute),Java開發者編碼比較簡單。 | SAX解析基於事件的編程方法。java開發編碼相對復雜 |
三、使用SAX讀取XML數據實例
books.xml:
<?xml version="1.0" encoding="UTF-8"?> <bookstore> <book id="1"> <name>冰與火之歌</name> <author>喬治馬丁</author> <year>2014</year> <price>89</price> </book> <book id="2"> <name>安徒生童話</name> <year>2004</year> <price>77</price> <language>English</language> </book> </bookstore>
SAXParserHandler.java:
public class SAXParserHandler extends DefaultHandler { String value = null; Book book = null; private ArrayList<Book> bookList = new ArrayList<Book>(); public ArrayList<Book> getBookList() { return bookList; } int bookIndex = 0; /** * 用來標識解析開始 */ @Override public void startDocument() throws SAXException { // TODO Auto-generated method stub super.startDocument(); System.out.println("SAX解析開始"); } /** * 用來標識解析結束 */ @Override public void endDocument() throws SAXException { // TODO Auto-generated method stub super.endDocument(); System.out.println("SAX解析結束"); } /** * 解析xml元素 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //調用DefaultHandler類的startElement方法 super.startElement(uri, localName, qName, attributes); if (qName.equals("book")) { bookIndex++; //創建一個book對象 book = new Book(); //開始解析book元素的屬性 System.out.println("======================開始遍歷某一本書的內容================="); //不知道book元素下屬性的名稱以及個數,如何獲取屬性名以及屬性值 int num = attributes.getLength(); for(int i = 0; i < num; i++){ System.out.print("book元素的第" + (i + 1) + "個屬性名是:" + attributes.getQName(i)); System.out.println("---屬性值是:" + attributes.getValue(i)); if (attributes.getQName(i).equals("id")) { book.setId(attributes.getValue(i)); } } } else if (!qName.equals("name") && !qName.equals("bookstore")) { System.out.print("節點名是:" + qName + "---"); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //調用DefaultHandler類的endElement方法 super.endElement(uri, localName, qName); //判斷是否針對一本書已經遍歷結束 if (qName.equals("book")) { bookList.add(book); book = null; System.out.println("======================結束遍歷某一本書的內容================="); } else if (qName.equals("name")) { book.setName(value); } else if (qName.equals("author")) { book.setAuthor(value); } else if (qName.equals("year")) { book.setYear(value); } else if (qName.equals("price")) { book.setPrice(value); } else if (qName.equals("language")) { book.setLanguage(value); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { // TODO Auto-generated method stub super.characters(ch, start, length); value = new String(ch, start, length); if (!value.trim().equals("")) { System.out.println("節點值是:" + value); } } }
SAXTest.java:
public class SAXTest { /** * @param args */ public static void main(String[] args) { //錕斤拷取一錕斤拷SAXParserFactory錕斤拷實錕斤拷 SAXParserFactory factory = SAXParserFactory.newInstance(); //通錕斤拷factory錕斤拷取SAXParser實錕斤拷 try { SAXParser parser = factory.newSAXParser(); //錕斤拷錕斤拷SAXParserHandler錕斤拷錕斤拷 SAXParserHandler handler = new SAXParserHandler(); parser.parse("books.xml", handler); System.out.println("~!~!~!共有" + handler.getBookList().size() + "本書"); for (Book book : handler.getBookList()) { System.out.println(book.getId()); System.out.println(book.getName()); System.out.println(book.getAuthor()); System.out.println(book.getYear()); System.out.println(book.getPrice()); System.out.println(book.getLanguage()); System.out.println("----finish----"); } } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Java高級特性 第14節 解析XML文檔(2) - SAX 技術