解析XML方式-DOM,SAX
students.xml
<?xml version="1.0" encoding="UTF-8"?> <students><student id="1"><name>張珊</name><age>22</age></student><student id="2"><name>王航</name><age>25</age></student><student id="3"><name>劉沙</name><age>26</age></student><student id="4"><name>張海</name><age>24</age></student> </students>
Person.java
package xmldom;public class Person {int id;String name;int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
一,DOM方式解析XML就是先把XML文檔都讀到內(nèi)存中,然后在用戶DOMAPI來(lái)訪問(wèn)樹形結(jié)構(gòu),獲取數(shù)據(jù)
解析的思路是:
1,將xml文件加載進(jìn)來(lái)
2,獲取文檔的根節(jié)點(diǎn)
3,獲取文檔根節(jié)點(diǎn)中的所有子節(jié)點(diǎn)的列表
4,獲取子節(jié)點(diǎn)列表中需要多去的節(jié)點(diǎn)信息
首先創(chuàng)建一個(gè)DocumentBuilderFactory實(shí)例,然后通過(guò)該實(shí)例來(lái)加載XML文檔(Document)文檔加載完畢以后,進(jìn)行節(jié)點(diǎn)獲取,先找到根節(jié)點(diǎn),在找到子節(jié)點(diǎn)。
package xmldom;import java.io.File; import java.io.IOException; import java.util.ArrayList;import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException;import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException;public class Main {/*** @param args*/public static void main(String[] args) {ArrayList<Person> studentslist=new ArrayList<Person>();DocumentBuilderFactory factory=null;//DOM解析器工廠DocumentBuilder builder=null;//DOM解析器Document document=null;//文檔對(duì)象try {//1,實(shí)例化DOM解析器工廠,工廠的作用是創(chuàng)建具體的解析器factory=DocumentBuilderFactory.newInstance();//2,通過(guò)工廠獲得DOM解析器builder=factory.newDocumentBuilder();//3,通過(guò)DOM解析器獲得文檔對(duì)象,可以解析File,InputStream等document=builder.parse(new File("students.xml"));//把這個(gè)文檔放在項(xiàng)目的根路徑下,與src目錄平行,就可以使用相對(duì)路徑來(lái)引用了//4,獲取文檔的根節(jié)點(diǎn)Element root=document.getDocumentElement();//5,由根節(jié)點(diǎn)獲取子節(jié)點(diǎn)列表NodeList nodelist=root.getElementsByTagName("student");//遍歷每個(gè)子節(jié)點(diǎn)Person person=null;for(int i=0;i<nodelist.getLength();i++){person=new Person();// 獲得元素,將節(jié)點(diǎn)強(qiáng)制轉(zhuǎn)換為元素。此時(shí)element就是一個(gè)具體的元素Element studentelement=(Element) nodelist.item(i); String id=studentelement.getAttribute("id");//元素獲得屬性值person.setId(Integer.valueOf(id));//獲取子元素:子元素name只有一個(gè)節(jié)點(diǎn).所以是item(0)Element Name=(Element) studentelement.getElementsByTagName("name").item(0);person.setName(Name.getFirstChild().getNodeValue());//獲得子元素的值,一定要加getFirstChild//獲取子元素:子元素name只有一個(gè)節(jié)點(diǎn).所以是item(0)Element Age=(Element) studentelement.getElementsByTagName("age").item(0);person.setAge(new Integer(Age.getFirstChild().getNodeValue()));//獲得子元素的值,一定要加getFirstChildstudentslist.add(person);} } catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}for(int i=0;i<studentslist.size();i++){System.out.println("ID:"+studentslist.get(i).getId()+" 姓名:"+studentslist.get(i).getName()+" 年齡:"+studentslist.get(i).getAge()); }}} 結(jié)果:
ID:1 姓名:張珊 年齡:22 ID:2 姓名:王航 年齡:25 ID:3 姓名:劉沙 年齡:26 ID:4 姓名:張海 年齡:24 DOM 的 API:
1.解析器工廠類:DocumentBuilderFactory
創(chuàng)建的方法:DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2.解析器:DocumentBuilder
創(chuàng)建方法:通過(guò)解析器工廠類來(lái)獲得 DocumentBuilder db = dbf.newDocumentBuilder();
3.文檔樹模型Document
創(chuàng)建方法:a.通過(guò)xml文檔 Document doc = db.parse("bean.xml"); b.將需要解析的xml文檔轉(zhuǎn)化為輸入流 InputStream is = new FileInputStream("bean.xml");
Document doc = db.parse(is);
Document對(duì)象代表了一個(gè)XML文檔的模型樹,所有的其他Node都以一定的順序包含在Document對(duì)象之內(nèi),排列成一個(gè)樹狀結(jié)構(gòu),以后對(duì)XML文檔的所有操作都與解析器無(wú)關(guān),直接在這個(gè)Document對(duì)象上進(jìn)行操作即可;
Document的方法:
4.節(jié)點(diǎn)列表類NodeList
NodeList代表了一個(gè)包含一個(gè)或者多個(gè)Node的列表,根據(jù)操作可以將其簡(jiǎn)化的看做為數(shù)組
5.節(jié)點(diǎn)類Node
Node對(duì)象是DOM中最基本的對(duì)象,代表了文檔樹中的抽象節(jié)點(diǎn)。但在實(shí)際使用中很少會(huì)直接使用Node對(duì)象,而是使用Node對(duì)象的子對(duì)象Element,Attr,Text等
6.元素類Element
是Node類最主要的子對(duì)象,在元素中可以包含屬性,因而Element中有存取其屬性的方法
二,使用SAX解析XML
SAX是Simple API for XML的縮寫,比DOM速度更快,更有效,占用內(nèi)存更小。他是逐行掃描,邊掃描邊解析,流式處理,是基于事件驅(qū)動(dòng)的,就是不用完全解析整個(gè)文檔,在按內(nèi)容順序解析文檔過(guò)程中,SAX會(huì)判斷當(dāng)前讀到的字符是否符合XML文件語(yǔ)法的某部分,如果符合,就會(huì)觸發(fā)事件,就是調(diào)用一些回調(diào)方法。
使用SAX解析XML的幾個(gè)步驟:
1,創(chuàng)建SAXParserFactory對(duì)象
2,調(diào)用SAXParserFactory的newSAXParser方法創(chuàng)建一個(gè)SAXParser對(duì)象
3,實(shí)例化一個(gè)繼承DefaultHandler的自定義對(duì)象
4,SAXParser對(duì)象的parser方法按自定義Handler規(guī)則解析xml文檔
MyHandler.java
package saxxml;import java.util.ArrayList;import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler;public class MyHandler extends DefaultHandler {ArrayList<Person> students;//要返回的對(duì)象集合StringBuilder sb;Person student;//當(dāng)遇到文檔開頭的時(shí)候,即開始解析XML根元素時(shí)調(diào)用該方法,調(diào)用這個(gè)方法,可以做一些預(yù)處理@Overridepublic void startDocument() throws SAXException {System.out.println("--startDocument--");students=new ArrayList<Person>();//實(shí)例化對(duì)象sb=new StringBuilder();}//當(dāng)讀到開始標(biāo)簽的時(shí),調(diào)用這個(gè)方法。即開始解析每個(gè)元素時(shí)都會(huì)調(diào)用該方法,uri表示命名空間,localName是不帶命名空間前綴的標(biāo)簽名,qName是帶命名空間前綴的標(biāo)簽名,attributes可以得到所有屬性,一般讀到的標(biāo)簽名在qName@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException { System.out.println("--startElement--"+qName);//如果讀到的開始標(biāo)簽是student,就實(shí)例化對(duì)象,設(shè)置idif(qName.equals("student")){student=new Person();student.setId(new Integer(attributes.getValue("id"))); }sb.setLength(0);//每次讀到開始標(biāo)簽將字符長(zhǎng)度設(shè)置為0,以便重新開始讀取元素內(nèi)的字符節(jié)點(diǎn)}/*這個(gè)方法處理xml文件讀到的內(nèi)容,第一個(gè)參數(shù)存放文件的內(nèi)容,注意是xml文件的全部?jī)?nèi)容早已經(jīng)在ch中,只是每次調(diào)用此函數(shù)時(shí)start和length會(huì)變化,* 后面兩個(gè)參數(shù)是讀到的字符串在這個(gè)數(shù)組中的起始位置和長(zhǎng)度,使用new String(ch,start,length)可以獲取內(nèi)容*/@Overridepublic void characters(char[] ch, int start, int length) throws SAXException { System.out.println("--characters()--"+new String(ch,start,length)+"start="+start+" length="+length);sb.append(new String(ch,start,length));//將讀取到數(shù)字符數(shù)組追加到builder中}//遇到結(jié)束標(biāo)簽的時(shí)候,調(diào)用這個(gè)方法@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {System.out.println("--endElement--"+qName);if(qName.equalsIgnoreCase("name")){student.setName(sb.toString());}else if(qName.equalsIgnoreCase("age")){student.setAge(new Integer(sb.toString()));}else if(qName.equalsIgnoreCase("student")){students.add(student);}}//文檔結(jié)束的時(shí)候,調(diào)用這個(gè)方法,可以做一些善后工作@Overridepublic void endDocument() throws SAXException { System.out.println("--endDocument--");} //返回對(duì)象集合public ArrayList<Person> getList(){return students;}}
Main.java
package saxxml;import java.io.File; import java.io.IOException; import java.util.ArrayList;import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory;import org.xml.sax.SAXException;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubtry {//1,創(chuàng)建一個(gè)SAXParserFactory對(duì)象SAXParserFactory factory=SAXParserFactory.newInstance();//2,調(diào)用SAXParserFactory中的newSAXParser方法創(chuàng)建一個(gè)SAXParser對(duì)象SAXParser parser=factory.newSAXParser();MyHandler myhandler=new MyHandler();//3,SAXParser對(duì)象使用自定義的Handler規(guī)則解析xml文件或xml文件流parser.parse(new File("students.xml"), myhandler);//遍歷返回的對(duì)象集合ArrayList<Person> list=myhandler.getList();for(int i=0;i<list.size();i++){System.out.println("ID:"+list.get(i).getId()+" 姓名:"+list.get(i).getName()+" 年齡:"+list.get(i).getAge());}} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} 輸出:
--startDocument-- --startElement--students --characters()--start=13 length=5//前面的空格是回車符\t.換行符\n,空格,的輸出 --startElement--student --characters()--start=35 length=9 --startElement--name --characters()--張珊start=50 length=2 --endElement--name --characters()--start=60 length=9 --startElement--age --characters()--22start=74 length=2 --endElement--age --characters()--start=83 length=5 --endElement--student --characters()--start=99 length=5 --startElement--student --characters()--start=121 length=9 --startElement--name --characters()--王航start=136 length=2 --endElement--name --characters()--start=146 length=9 --startElement--age --characters()--25start=160 length=2 --endElement--age --characters()--start=169 length=5 --endElement--student --characters()--start=185 length=5 --startElement--student --characters()--start=207 length=9 --startElement--name --characters()--劉沙start=222 length=2 --endElement--name --characters()--start=232 length=9 --startElement--age --characters()--26start=246 length=2 --endElement--age --characters()--start=255 length=5 --endElement--student --characters()--start=271 length=5 --startElement--student --characters()--start=293 length=9 --startElement--name --characters()--張海start=308 length=2 --endElement--name --characters()--start=318 length=9 --startElement--age --characters()--24start=332 length=2 --endElement--age --characters()--start=341 length=5 --endElement--student --characters()-- start=357 length=1 --endElement--students --endDocument-- ID:1 姓名:張珊 年齡:22 ID:2 姓名:王航 年齡:25 ID:3 姓名:劉沙 年齡:26 ID:4 姓名:張海 年齡:24
分析:用SAX解析XML采用的是從上而下的基于事件驅(qū)動(dòng)的解析方式,在解析過(guò)程中會(huì)視情況自動(dòng)調(diào)用startDocument()、startElement()、characters()、endElement()、endDocument()等相關(guān)的方法。
由編譯執(zhí)行的結(jié)果來(lái)看:
1,startDocument()方法只會(huì)在文檔開始解析的時(shí)候被調(diào)用,每次解析只會(huì)調(diào)用一次。,
2,startElement()方法每次在開始解析一個(gè)元素,即遇到元素標(biāo)簽開始的時(shí)候都會(huì)調(diào)用。
3,characters()方法也是在每次解析到元素標(biāo)簽攜帶的內(nèi)容時(shí)都會(huì)調(diào)用,即在startElement調(diào)用后,調(diào)用characters時(shí)讀到的內(nèi)容值,在endElement調(diào)用后,調(diào)用characters時(shí)讀到的回車符,換行符和空格。即使該元素標(biāo)簽的內(nèi)容為空或換行。而且如果元素內(nèi)嵌套元素,在父元素結(jié)束標(biāo)簽前, characters()方法會(huì)再次被調(diào)用,此處需要注意。
4,endElement()方法每次在結(jié)束解析一個(gè)元素,即遇到元素標(biāo)簽結(jié)束的時(shí)候都會(huì)調(diào)用。
5,endDocument() startDocument()方法只會(huì)在文檔解析結(jié)束的時(shí)候被調(diào)用,每次解析只會(huì)調(diào)用一次。
其實(shí)參數(shù)char[] ch中早已經(jīng)加載了文檔,每次調(diào)用的時(shí)候改變的是start,length
總結(jié)
以上是生活随笔為你收集整理的解析XML方式-DOM,SAX的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 质数因子
- 下一篇: java设计模式-Builder创建者模