XML文件解析
一般的XML文件解析有三种:
1>DOM
2>JDOM
3>SAX
之前所学的xml文件解析忘得差不多了,抽空回忆了一下,过程不再叙述了。
原料准备:
待解析的xml源文件books.xml:
1 <?xml version="1.0" encoding="gb2312"?> 2 <books> 3 <book> 4 <title>JSP 应用开发指南</title> 5 <url newWindow="no">http://java.sun.com</url> 6 <author>Author 001</author> 7 <date> 8 <day>23</day> 9 <month>1</month> 10 <year>2006</year> 11 </date> 12 <description>一本详尽介绍JSP技术的书.</description> 13 </book> 14 <book> 15 <title>Ant 技术详解</title> 16 <url newWindow="no">http://ant.apache.org/</url> 17 <author>Author 002</author> 18 <date> 19 <day>25</day> 20 <month>2</month> 21 <year>2007</year> 22 </date> 23 <description>一本详尽介绍Ant技术的书.</description> 24 </book> 25 <book> 26 <title>Apache 技术详解</title> 27 <url newWindow="no">http://www.apache.org/</url> 28 <author>Author 003</author> 29 <date> 30 <day>26</day> 31 <month>3</month> 32 <year>2008</year> 33 </date> 34 <description>一本详尽介绍Apache技术的书.</description> 35 </book> 36 </books>
一>采用DOM解析
DOM 虽然是 W3C 的标准,提供了标准的解析方式,但它的解析效率一直不尽如人意,因为使用DOM解析XML时,解析器读入整个文档并构建一个驻留内存的树结构(节点树),然后您的代码才可以使用 DOM 的标准接口来操作这个树结构。但大部分情况下我们只对文档的部分内容感兴趣,根本就不用先解析整个文档,并且从节点树的根节点来索引一些我们需要的数据也是非常耗时的。
1 package com.pb.dom; 2 3 import java.io.IOException; 4 5 import javax.xml.parsers.DocumentBuilder; 6 import javax.xml.parsers.DocumentBuilderFactory; 7 import javax.xml.parsers.ParserConfigurationException; 8 9 import org.w3c.dom.Document; 10 import org.w3c.dom.Element; 11 import org.w3c.dom.NodeList; 12 import org.xml.sax.SAXException; 13 14 /** 15 * 通过DOM解析XML文件 16 * @author Administrator 17 * 18 */ 19 public class domjtest { 20 21 public static void main(String[] args) { 22 // 建立解析器工厂 23 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 24 25 try { 26 // 获得解析器对象 27 DocumentBuilder builder = factory.newDocumentBuilder(); 28 29 // 对XML文档进行解析,获得Document对象 30 Document doc = builder.parse("D:/booktest/books.xml"); 31 32 doc.normalize(); 33 34 // 获取所以book元素列表 35 NodeList books = doc.getElementsByTagName("book"); 36 37 // 对列表进行循环遍历,取出其中的元素 38 for (int i = 0; i < books.getLength(); i++) { 39 // 获取book元素 40 Element book = (Element) books.item(i); 41 42 // 依次打印book的子元素 43 System.out.println("title:" 44 + book.getElementsByTagName("title").item(0) 45 .getFirstChild().getNodeValue()); 46 47 System.out.println("url:" 48 + book.getElementsByTagName("url").item(0) 49 .getFirstChild().getNodeValue()); 50 51 System.out.println("author:" 52 + book.getElementsByTagName("author").item(0) 53 .getFirstChild().getNodeValue()); 54 55 Element bookdate = (Element) book.getElementsByTagName("date") 56 .item(0); 57 58 String day = bookdate.getElementsByTagName("day").item(0) 59 .getFirstChild().getNodeValue(); 60 61 String month = bookdate.getElementsByTagName("month").item(0) 62 .getFirstChild().getNodeValue(); 63 64 String year = bookdate.getElementsByTagName("year").item(0) 65 .getFirstChild().getNodeValue(); 66 67 System.out.println("date:" + day + "-" + month + "-" + year); 68 69 System.out.println("description:" 70 + book.getElementsByTagName("description").item(0) 71 .getFirstChild().getNodeValue()); 72 } 73 74 } catch (ParserConfigurationException e) { 75 // TODO Auto-generated catch block 76 e.printStackTrace(); 77 } catch (SAXException e) { 78 // TODO Auto-generated catch block 79 e.printStackTrace(); 80 } catch (IOException e) { 81 // TODO Auto-generated catch block 82 e.printStackTrace(); 83 } 84 85 } 86 87 }
二>采用JDOM解析
JDOM(Java Document Object Model):java文档对象模型。
DOM被设计为用于完成几乎所有的XML操作任务,同时它又是与语言无关,这就导致DOM的API庞大而复杂。
为了给JAVA程序员提供一套简单易用的操作XML的API,java技术专家Jason Hunter和Brett McLaughlin创建了JDOM。
JDOM利用Java语言的优秀特性,包括方法重载,集合,反射以及JAVA程序员熟悉的编程风格,极大的简化了对XML文档的处理。
和DOM类似,JDOM也使用对象树来表示XML文档:
<name>张三</name>
要想得到“张三”这个文本节点,在DOM中:
String content = element.getFirstChild().getNodeValue();
在JDOM中:
String content = element.getText();
注意:JDOM使用SAX解析器(例如Apache的Xerces),默认JDOM使用JAXP来选择解析器。JDOM还可以接收W3C DOM格式的内容,同时,JDOM也提供了从JDOM树到SAX事件流或W3C DOM树的输出机制。
1 package com.pb.jdom; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.util.List; 6 7 import org.jdom.Document; 8 import org.jdom.Element; 9 import org.jdom.JDOMException; 10 import org.jdom.input.SAXBuilder; 11 12 /** 13 * 通过JDOM解析XML文件 14 * 15 * @author Administrator 16 * 17 */ 18 public class jdomtest { 19 20 public static void main(String[] args) { 21 // 得到一个解析器对象 22 SAXBuilder sb = new SAXBuilder(); 23 24 try { 25 // 对XML文档进行解析,获得Document对象 26 Document doc = (Document) sb 27 .build(new File("D:/booktest/books.xml")); 28 29 // 得到根元素 30 Element root = doc.getRootElement(); 31 32 // 得到根元素下的所有子元素集合 33 List books = root.getChildren(); 34 35 Element book = null; 36 37 // 对列表进行循环遍历,取出其中的元素 38 for (int i = 0; i < books.size(); i++) { 39 // 得到一本书元素 40 book = (Element) books.get(i); 41 42 // 依次打印book的子元素 43 System.out.println("title:" + book.getChild("title").getText()); 44 45 System.out.println("url:" + book.getChild("url").getText()); 46 47 System.out.println("author:" 48 + book.getChild("author").getText()); 49 50 Element bookdate = (Element) book.getChild("date"); 51 52 String day = bookdate.getChild("day").getText(); 53 54 String month = bookdate.getChild("month").getText(); 55 56 String year = bookdate.getChild("year").getText(); 57 58 System.out.println("date:" + day + "-" + month + "-" + year); 59 60 System.out.println("description:" 61 + book.getChild("description").getText()); 62 } 63 64 } catch (JDOMException e1) { 65 // TODO Auto-generated catch block 66 e1.printStackTrace(); 67 } catch (IOException e1) { 68 // TODO Auto-generated catch block 69 e1.printStackTrace(); 70 } 71 72 } 73 74 }
三>采用SAX解析
SAX是Simple API for XML的缩写,它并不是由W3C官方所提出的标准。
SAX是一种轻量型的方法,不像DOM解析时,把XML文档全部载入内存中,在PC上操作,Dom还有优势,但在手机中端上则无优势,因为手机内存和硬件都比不上PC强。
SAX采用基于事件驱动的处理方式,它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理。
在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser()方法来解析XML文档,并根据文档的内容产生事件。
而事件处理器则是org.xml.sax包中的ContentHander、DTDHander、ErrorHandler,以及EntityResolver这4个接口,它们分别处理事件源在解析XML文档过程中产生的不同种类的事件。
在开发中没有必要直接从这4个接口直接继承,因为org.xml.sax.helper包提供了类DefaultHandler,其继承了这4个接口,在实际开发中直接从DefaultHandler继承并实现相关函数就可以了。
SAX是一种XML解析的替代方法。相比于文档对象模型DOM,SAX 是读取和操作 XML 数据的更快速、更轻量的方
法。SAX 允许您在读取文档时处理它,从而不必等待整个文档被存储之后才采取操作。它不涉及 DOM 所必需的开销和概念跳跃。
SAX API是一个基于事件的API ,适用于处理数据流,即随着数据的流动而依次处理数据。
SAX API 在其解析您的文档时发生一定事件的时候会通知您。在您对其响应时,您不作保存的数据将会 被抛弃。
SAX API中主要有四种处理事件的接口,它们分别是ContentHandler,DTDHandler, EntityResolver 和 ErrorHandler 。一般只要继承DefaultHandler 类 ,再重写覆盖一部分处理事件的方法就可以开始进行xml文件解析了。( 实际上DefaultHandler就是实现了上面的四个事件处理器接口,然后提供了每个抽象方法的默认实现。)
Book.java
1 package com.pb.sax; 2 3 public class Book 4 { 5 private String title; 6 private String url; 7 private String author; 8 private BookDate date; 9 private String day; 10 private String month; 11 private String year; 12 private String description; 13 public String getTitle() { 14 return title; 15 } 16 public void setTitle(String title) { 17 this.title = title; 18 } 19 public String getUrl() { 20 return url; 21 } 22 public void setUrl(String url) { 23 this.url = url; 24 } 25 public String getAuthor() { 26 return author; 27 } 28 public void setAuthor(String author) { 29 this.author = author; 30 } 31 public BookDate getDate() { 32 return date; 33 } 34 public void setDate(BookDate date) { 35 this.date = date; 36 } 37 public String getDay() { 38 return day; 39 } 40 public void setDay(String day) { 41 this.day = day; 42 } 43 public String getMonth() { 44 return month; 45 } 46 public void setMonth(String month) { 47 this.month = month; 48 } 49 public String getYear() { 50 return year; 51 } 52 public void setYear(String year) { 53 this.year = year; 54 } 55 public String getDescription() { 56 return description; 57 } 58 public void setDescription(String description) { 59 this.description = description; 60 } 61 62 63 }
BookDate.java
1 package com.pb.sax; 2 3 public class BookDate 4 { 5 private String day; 6 private String month; 7 private String year; 8 public String getDay() { 9 return day; 10 } 11 public void setDay(String day) { 12 this.day = day; 13 } 14 public String getMonth() { 15 return month; 16 } 17 public void setMonth(String month) { 18 this.month = month; 19 } 20 public String getYear() { 21 return year; 22 } 23 public void setYear(String year) { 24 this.year = year; 25 } 26 27 28 }
saxtest.java
1 package com.pb.sax; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import javax.xml.parsers.ParserConfigurationException; 9 import javax.xml.parsers.SAXParser; 10 import javax.xml.parsers.SAXParserFactory; 11 12 import org.xml.sax.Attributes; 13 import org.xml.sax.SAXException; 14 import org.xml.sax.helpers.DefaultHandler; 15 16 /** 17 * 通过SAX解析XML文件 18 * @author Administrator 19 * 20 */ 21 public class saxtest extends DefaultHandler 22 { 23 //存放遍历集合 24 private List<Book> list; 25 26 //定义Book对象 27 private Book book; 28 29 //定义Book日期属性 30 private BookDate date; 31 32 //定义元素节点名称 33 private String tagname; 34 35 public List<Book> getList() { 36 return list; 37 } 38 39 public void setList(List<Book> list) { 40 this.list = list; 41 } 42 43 public Book getBook() { 44 return book; 45 } 46 47 public void setBook(Book book) { 48 this.book = book; 49 } 50 51 public String getTagname() { 52 return tagname; 53 } 54 55 public void setTagname(String tagname) { 56 this.tagname = tagname; 57 } 58 59 //只调用一次, 初始化booklist集合 60 @Override 61 public void startDocument() throws SAXException { 62 // TODO Auto-generated method stub 63 list = new ArrayList<Book>(); 64 65 } 66 67 //调用多次 开始解析文件 68 @Override 69 public void startElement(String uri, String localName, String qName, 70 Attributes attributes) throws SAXException { 71 // TODO Auto-generated method stub 72 if (qName.equals("book")) { 73 book = new Book(); 74 } 75 else if (qName.equals("date")) 76 { 77 date = new BookDate(); 78 } 79 80 this.tagname = qName; 81 } 82 83 //调用多次 84 @Override 85 public void endElement(String uri, String localName, String qName) 86 throws SAXException { 87 // TODO Auto-generated method stub 88 if (qName.equals("book")) { 89 this.list.add(this.book); 90 } 91 else if (qName.equals("date")) 92 { 93 this.book.setDate(this.date); 94 } 95 96 this.tagname = null; 97 } 98 99 //只调用一次 100 @Override 101 public void endDocument() throws SAXException { 102 // TODO Auto-generated method stub 103 super.endDocument(); 104 } 105 106 //调用多次 107 @Override 108 public void characters(char[] ch, int start, int length) 109 throws SAXException { 110 // TODO Auto-generated method stub 111 if (this.tagname != null) 112 { 113 String date = new String (ch, start, length); 114 115 if (this.tagname.equals("title")) 116 { 117 this.book.setTitle(date); 118 } 119 else if (this.tagname.equals("url")) 120 { 121 this.book.setUrl(date); 122 } 123 else if (this.tagname.equals("author")) 124 { 125 this.book.setAuthor(date); 126 } 127 else if (this.tagname.equals("day")) 128 { 129 this.date.setDay(date); 130 } 131 else if (this.tagname.equals("month")) 132 { 133 this.date.setMonth(date); 134 } 135 else if (this.tagname.equals("year")) 136 { 137 this.date.setYear(date); 138 } 139 else if (this.tagname.equals("description")) 140 { 141 this.book.setDescription(date); 142 } 143 144 145 } 146 } 147 148 public static void main(String[] args) 149 { 150 // 构建SAXParser 151 SAXParser parser = null; 152 153 try { 154 parser = SAXParserFactory.newInstance().newSAXParser(); 155 156 // 实例化 DefaultHandler对象 157 saxtest sax = new saxtest(); 158 159 // 加载资源文件 转化为一个输入流 160 InputStream stream = saxtest.class.getResourceAsStream("books.xml"); 161 162 // 调用parse()方法 163 parser.parse(stream, sax); 164 165 // 获得集合 166 List<Book> booklist = sax.getList(); 167 168 // 依次循环,遍历结果 169 for (Book book : booklist) { 170 System.out.println(book.getTitle()); 171 System.out.println(book.getUrl()); 172 System.out.println(book.getAuthor()); 173 System.out.println(book.getDate().getYear() + "-" 174 + book.getDate().getMonth() + "-" 175 + book.getDate().getDay()); 176 System.out.println(book.getDescription()); 177 System.out.println("========================"); 178 179 } 180 181 } catch (ParserConfigurationException | SAXException e) { 182 // TODO Auto-generated catch block 183 e.printStackTrace(); 184 } catch (IOException e) { 185 // TODO Auto-generated catch block 186 e.printStackTrace(); 187 } 188 189 } 190 191 192 193 194 195 196 197 198 199 }