解析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來訪問樹形結(jié)構(gòu),獲取數(shù)據(jù)
解析的思路是:
1,將xml文件加載進來
2,獲取文檔的根節(jié)點
3,獲取文檔根節(jié)點中的所有子節(jié)點的列表
4,獲取子節(jié)點列表中需要多去的節(jié)點信息
首先創(chuàng)建一個DocumentBuilderFactory實例,然后通過該實例來加載XML文檔(Document)文檔加載完畢以后,進行節(jié)點獲取,先找到根節(jié)點,在找到子節(jié)點。
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;//文檔對象try {//1,實例化DOM解析器工廠,工廠的作用是創(chuàng)建具體的解析器factory=DocumentBuilderFactory.newInstance();//2,通過工廠獲得DOM解析器builder=factory.newDocumentBuilder();//3,通過DOM解析器獲得文檔對象,可以解析File,InputStream等document=builder.parse(new File("students.xml"));//把這個文檔放在項目的根路徑下,與src目錄平行,就可以使用相對路徑來引用了//4,獲取文檔的根節(jié)點Element root=document.getDocumentElement();//5,由根節(jié)點獲取子節(jié)點列表NodeList nodelist=root.getElementsByTagName("student");//遍歷每個子節(jié)點Person person=null;for(int i=0;i<nodelist.getLength();i++){person=new Person();// 獲得元素,將節(jié)點強制轉(zhuǎn)換為元素。此時element就是一個具體的元素Element studentelement=(Element) nodelist.item(i); String id=studentelement.getAttribute("id");//元素獲得屬性值person.setId(Integer.valueOf(id));//獲取子元素:子元素name只有一個節(jié)點.所以是item(0)Element Name=(Element) studentelement.getElementsByTagName("name").item(0);person.setName(Name.getFirstChild().getNodeValue());//獲得子元素的值,一定要加getFirstChild//獲取子元素:子元素name只有一個節(jié)點.所以是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)建方法:通過解析器工廠類來獲得 DocumentBuilder db = dbf.newDocumentBuilder();
3.文檔樹模型Document
創(chuàng)建方法:a.通過xml文檔 Document doc = db.parse("bean.xml"); b.將需要解析的xml文檔轉(zhuǎn)化為輸入流 InputStream is = new FileInputStream("bean.xml");
Document doc = db.parse(is);
Document對象代表了一個XML文檔的模型樹,所有的其他Node都以一定的順序包含在Document對象之內(nèi),排列成一個樹狀結(jié)構(gòu),以后對XML文檔的所有操作都與解析器無關(guān),直接在這個Document對象上進行操作即可;
Document的方法:
4.節(jié)點列表類NodeList
NodeList代表了一個包含一個或者多個Node的列表,根據(jù)操作可以將其簡化的看做為數(shù)組
5.節(jié)點類Node
Node對象是DOM中最基本的對象,代表了文檔樹中的抽象節(jié)點。但在實際使用中很少會直接使用Node對象,而是使用Node對象的子對象Element,Attr,Text等
6.元素類Element
是Node類最主要的子對象,在元素中可以包含屬性,因而Element中有存取其屬性的方法
二,使用SAX解析XML
SAX是Simple API for XML的縮寫,比DOM速度更快,更有效,占用內(nèi)存更小。他是逐行掃描,邊掃描邊解析,流式處理,是基于事件驅(qū)動的,就是不用完全解析整個文檔,在按內(nèi)容順序解析文檔過程中,SAX會判斷當前讀到的字符是否符合XML文件語法的某部分,如果符合,就會觸發(fā)事件,就是調(diào)用一些回調(diào)方法。
使用SAX解析XML的幾個步驟:
1,創(chuàng)建SAXParserFactory對象
2,調(diào)用SAXParserFactory的newSAXParser方法創(chuàng)建一個SAXParser對象
3,實例化一個繼承DefaultHandler的自定義對象
4,SAXParser對象的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;//要返回的對象集合StringBuilder sb;Person student;//當遇到文檔開頭的時候,即開始解析XML根元素時調(diào)用該方法,調(diào)用這個方法,可以做一些預處理@Overridepublic void startDocument() throws SAXException {System.out.println("--startDocument--");students=new ArrayList<Person>();//實例化對象sb=new StringBuilder();}//當讀到開始標簽的時,調(diào)用這個方法。即開始解析每個元素時都會調(diào)用該方法,uri表示命名空間,localName是不帶命名空間前綴的標簽名,qName是帶命名空間前綴的標簽名,attributes可以得到所有屬性,一般讀到的標簽名在qName@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException { System.out.println("--startElement--"+qName);//如果讀到的開始標簽是student,就實例化對象,設(shè)置idif(qName.equals("student")){student=new Person();student.setId(new Integer(attributes.getValue("id"))); }sb.setLength(0);//每次讀到開始標簽將字符長度設(shè)置為0,以便重新開始讀取元素內(nèi)的字符節(jié)點}/*這個方法處理xml文件讀到的內(nèi)容,第一個參數(shù)存放文件的內(nèi)容,注意是xml文件的全部內(nèi)容早已經(jīng)在ch中,只是每次調(diào)用此函數(shù)時start和length會變化,* 后面兩個參數(shù)是讀到的字符串在這個數(shù)組中的起始位置和長度,使用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é)束標簽的時候,調(diào)用這個方法@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é)束的時候,調(diào)用這個方法,可以做一些善后工作@Overridepublic void endDocument() throws SAXException { System.out.println("--endDocument--");} //返回對象集合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)建一個SAXParserFactory對象SAXParserFactory factory=SAXParserFactory.newInstance();//2,調(diào)用SAXParserFactory中的newSAXParser方法創(chuàng)建一個SAXParser對象SAXParser parser=factory.newSAXParser();MyHandler myhandler=new MyHandler();//3,SAXParser對象使用自定義的Handler規(guī)則解析xml文件或xml文件流parser.parse(new File("students.xml"), myhandler);//遍歷返回的對象集合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ū)動的解析方式,在解析過程中會視情況自動調(diào)用startDocument()、startElement()、characters()、endElement()、endDocument()等相關(guān)的方法。
由編譯執(zhí)行的結(jié)果來看:
1,startDocument()方法只會在文檔開始解析的時候被調(diào)用,每次解析只會調(diào)用一次。,
2,startElement()方法每次在開始解析一個元素,即遇到元素標簽開始的時候都會調(diào)用。
3,characters()方法也是在每次解析到元素標簽攜帶的內(nèi)容時都會調(diào)用,即在startElement調(diào)用后,調(diào)用characters時讀到的內(nèi)容值,在endElement調(diào)用后,調(diào)用characters時讀到的回車符,換行符和空格。即使該元素標簽的內(nèi)容為空或換行。而且如果元素內(nèi)嵌套元素,在父元素結(jié)束標簽前, characters()方法會再次被調(diào)用,此處需要注意。
4,endElement()方法每次在結(jié)束解析一個元素,即遇到元素標簽結(jié)束的時候都會調(diào)用。
5,endDocument() startDocument()方法只會在文檔解析結(jié)束的時候被調(diào)用,每次解析只會調(diào)用一次。
其實參數(shù)char[] ch中早已經(jīng)加載了文檔,每次調(diào)用的時候改變的是start,length
總結(jié)
以上是生活随笔為你收集整理的解析XML方式-DOM,SAX的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 质数因子
- 下一篇: Android取消EditText自动获