SAX解析XML

来源:互联网 发布:之知为知之不知为不知 编辑:程序博客网 时间:2024/06/07 16:42
常识:<?为XML的文档开始标签,<为元素开始标签,</为元素结束标签。SAX就是根据<?、<、</、>这几个标签来解析XML的。
  • startDocument()方法只会在文档开始解析的时候遇到<?被调用,故每次解析只会调用一次。
  • startElement()方法每次在开始解析一个元素,即遇到元素标签开始<的时候都会调用。
  • characters()方法也是在每次解析到元素标签携带的内容时都会调用,即使该元素标签的内容为空或换行。而且如果元素内嵌套元素,在父元素结束标签前, characters()方法会再次被调用,此处需要注意。(简单理解,两个标签之间都会调用,当然,这两个标签肯定是紧挨着的两个标签)
  • endElement()方法每次在结束解析一个元素,即遇到元素标签结束</的时候都会调用。
  • endDocument() startDocument()方法只会在文档解析结束的时候被调用,每次解析只会调用一次。
例一:
现F盘有class.xml文件,内容如下:
<?xml version="1.0" encoding="gbk"?><class>    <stu id="001">       <name>Allen</name>       <sex>男</sex>       <age>20</age>    </stu>    <stu id="001">       <name>Allen</name>       <sex>男</sex>       <age>20</age>    </stu>    <stu id="002">       <name>namy</name>       <sex>女</sex>       <age>18</age>    </stu>    <stu id="003">       <name>lufy</name>       <sex>男</sex>       <age>18</age>     </stu></class>
现在要把所有的stu内容解析出来:
(1)工具类:
package com.school.handler;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;public class Myhandler extends DefaultHandler {// 存储正在解析的元素的数据private Map<String, String> map = null;// 存储所有解析的元素的数据private List<Map<String, String>> list = null;// 正在解析的元素的名字String currentTag = null;// 正在解析的元素的元素值String currentValue = null;// 开始解析的元素String nodeName = null;public Myhandler(String nodeName) {// TODO Auto-generated constructor stubthis.nodeName = nodeName;}public List<Map<String, String>> getList() {return list;}// 开始解析文档,即开始解析XML根元素时调用该方法@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stubSystem.out.println("--startDocument()--");// 初始化Maplist = new ArrayList<Map<String, String>>();}// 开始解析每个元素时都会调用该方法@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {// TODO Auto-generated method stub// 判断正在解析的元素是不是开始解析的元素System.out.println("--startElement()--" + qName);if (qName.equals(nodeName)) {map = new HashMap<String, String>();}// 判断正在解析的元素是否有属性值,如果有则将其全部取出并保存到map对象中,如:<person id=" "></person>if (attributes != null && map != null) {for (int i = 0; i < attributes.getLength(); i++) {map.put(attributes.getQName(i), attributes.getValue(i));//System.err.println(attributes.getQName(i)+attributes.getValue(i));}}currentTag = qName; // 正在解析的元素}// 解析到每个元素的内容时会调用此方法@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {// TODO Auto-generated method stubSystem.out.println("--characters()--");if (currentTag != null && map != null) {currentValue = new String(ch, start, length);// 如果内容不为空和空格,也不是换行符则将该元素名和值和存入map中if (currentValue != null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")) {map.put(currentTag, currentValue);System.out.println("-----" + currentTag + " " + currentValue);}// 当前的元素已解析过,将其置空用于下一个元素的解析,去掉也对//currentTag = null;//currentValue = null;}}// 每个元素结束的时候都会调用该方法@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {// TODO Auto-generated method stubSystem.out.println("--endElement()--" + qName);// 判断是否为一个节点结束的元素标签if (qName.equals(nodeName)) {list.add(map);}}// 结束解析文档,即解析根元素结束标签时调用该方法@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubSystem.out.println("--endDocument()--");super.endDocument();}}

(2)服务应用类:

package com.school.service;import java.io.File;import java.io.InputStream;import java.util.List;import java.util.Map;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import com.school.handler.Myhandler;public class SaxService {public static List<Map<String, String>> ReadXML(File uri, String NodeName) {try {// 创建一个解析XML的工厂对象SAXParserFactory parserFactory = SAXParserFactory.newInstance();// 创建一个解析XML的对象SAXParser parser = parserFactory.newSAXParser();// 创建一个解析助手类Myhandler myhandler = new Myhandler("stu");parser.parse(uri, myhandler);return myhandler.getList();} catch (Exception e) {e.printStackTrace();} finally {}return null;}}

(3)测试类:
package com.school.main;import java.io.File;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import com.school.service.SaxService;public class XmlSaxTest {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubFile file=new File("F:"+File.separator+"class.xml");ArrayList<Map<String, String>> list = (ArrayList<Map<String, String>>) SaxService.ReadXML(file, "class");/* * for(int i=0 ;i<list.size();i++){ HashMap<String, String> * temp=(HashMap<String, String>) list.get(i); Iterator<String> * iterator=temp.keySet().iterator(); while(iterator.hasNext()){ String * key=iterator.next().toString(); String value=temp.get(key); * System.out.print(key+" "+value+"--"); } } */System.out.println(list.toString());}}

运行,控制台输出如下:
--startDocument()--
--startElement()--class
--characters()--
--startElement()--stu
--characters()--
--startElement()--name
--characters()--
-----name Allen
--endElement()--name
--characters()--
--startElement()--sex
--characters()--
-----sex 男
--endElement()--sex
--characters()--
--startElement()--age
--characters()--
-----age 20
--endElement()--age
--characters()--
--endElement()--stu
--characters()--
--startElement()--stu
--characters()--
--startElement()--name
--characters()--
-----name Allen
--endElement()--name
--characters()--
--startElement()--sex
--characters()--
-----sex 男
--endElement()--sex
--characters()--
--startElement()--age
--characters()--
-----age 20
--endElement()--age
--characters()--
--endElement()--stu
--characters()--
--startElement()--stu
--characters()--
--startElement()--name
--characters()--
-----name namy
--endElement()--name
--characters()--
--startElement()--sex
--characters()--
-----sex 女
--endElement()--sex
--characters()--
--startElement()--age
--characters()--
-----age 18
--endElement()--age
--characters()--
--endElement()--stu
--characters()--
--startElement()--stu
--characters()--
--startElement()--name
--characters()--
-----name lufy
--endElement()--name
--characters()--
--startElement()--sex
--characters()--
-----sex 男
--endElement()--sex
--characters()--
--startElement()--age
--characters()--
-----age 18
--endElement()--age
--characters()--
--endElement()--stu
--characters()--
--endElement()--class
--endDocument()--
[{sex=男, name=Allen, id=001, age=20}, {sex=男, name=Allen, id=001, age=20}, {sex=女, name=namy, id=002, age=18}, {sex=男, name=lufy, id=003, age=18}]

例二、
现F盘有一个book.xml文件:
<?xml version="1.0" encoding="GB2312"?><bookstore>   <book category="COOKING">     <title lang="en">西游记</title>     <author>吴承恩</author>     <year>2005</year>     <price>30.00</price>  </book>   <book category="COOKING">     <title lang="en">水浒传</title>     <author>施耐庵</author>     <year>2003</year>     <price>29.00</price>   </book></bookstore>

现在把每个book解析成一个BookInfo类,用List来保存所有的BookInfo对象。
(1)实体类:
package com.booksax.entity;import java.io.Serializable;public class BookInfo implements Serializable{private String title;private String author;private String year;private String price;private String id;@Overridepublic String toString() {return "BookInfo [title=" + title + ", author=" + author + ", year=" + year + ", price=" + price + ", id=" + id+ "]";}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getYear() {return year;}public void setYear(String year) {this.year = year;}public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}}

(2)service:
package com.booksax.service;import java.util.ArrayList;import java.util.List;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import com.booksax.entity.BookInfo;public class BookInfoSaxService extends DefaultHandler {private List<BookInfo> bookList;//最后想要的结果,所有书的集合private String preTag;//当前解析的元素名称private BookInfo book;private String nodeName;//目标标签public BookInfoSaxService(String nodeName){bookList=new ArrayList<>();this.nodeName=nodeName;}public List<BookInfo> getBookList() {return bookList;}@Overridepublic void startDocument() throws SAXException {//System.out.println("****开始解析文档****");}@Overridepublic void endDocument() throws SAXException {//System.out.println("****结束解析文档****");}@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {System.out.println("开始解析元素"+qName);if(qName.equals(nodeName)){//如果解析到目标标签,new 一个新的BookInfo对象book=new BookInfo();if(attributes!=null){String id=attributes.getValue(0);book.setId(id);}}preTag=qName;}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {//System.out.println("结束"+qName);if(qName.equals(nodeName)){bookList.add(book);}}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {String str=new String(ch, start, length).trim();if(str!=null && !str.equals("")){//不是空的时候,说明是文本if(preTag.equals("title")){//是title标签book.setTitle(str);}if(preTag.equals("author")){//是title标签book.setAuthor(str);}if(preTag.equals("year")){book.setYear(str);}if(preTag.equals("price")){book.setPrice(str);}}}}

(3)测试类:
package com.booksax.main;import java.io.File;import java.io.FileInputStream;import java.io.FileReader;import java.io.IOException;import java.util.List;import javax.xml.parsers.ParserConfigurationException;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.xml.sax.SAXException;import com.booksax.entity.BookInfo;import com.booksax.service.BookInfoSaxService;public class BookManagerXmlTester {public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {SAXParserFactory factory=SAXParserFactory.newInstance();SAXParser parser=factory.newSAXParser();    File file=new File("F:"+File.separator+"book.xml");    BookInfoSaxService service=new BookInfoSaxService("book");parser.parse(file, service);List<BookInfo> bookList=service.getBookList();for(BookInfo book:bookList){System.out.println(book);}}}

控制台输出如下:
开始解析元素bookstore
开始解析元素book
开始解析元素title
开始解析元素author
开始解析元素year
开始解析元素price
开始解析元素book
开始解析元素title
开始解析元素author
开始解析元素year
开始解析元素price
BookInfo [title=西游记, author=吴承恩, year=2005, price=30.00, id=COOKING]
BookInfo [title=水浒传, author=施耐庵, year=2003, price=29.00, id=COOKING]

原创粉丝点击