1、DOM
DOM解析XML文件時,會將XML文件的所有內容讀取到內存中,然後允許您使用DOM API遍歷XML樹、檢索所需的數據。使用DOM操作XML的代碼看起來比較直觀,並且,在某些方面比基於SAX的實現更加簡單。但是,因爲DOM需要將 XML文件的所有內容讀取到內存中,所以內存的消耗比較大,特別對於運行Android的移動設備來說,因爲設備的資源比較寶貴,所以建議還是採用SAX 來解析XML文件,當然,如果XML文件的內容比較小採用DOM是可行的。
在解析之後每一個元素都會以Node的形式在內存中進行存儲
接下來使用代碼進行演示
XML文件內容
<?xml version="1.0" encoding="UTF-8" standalone="no"?><書架>
<書>
<名稱>平凡的世界</名稱>
<作者>路遙</作者>
<售價>50</售價>
</書>
<書>
<名稱>人生哲思錄</名稱>
<作者>周國平</作者>
<售價>2000</售價>
</書>
</書架>
java代碼內容
package XML_Study.DOM_Study;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* DocumentBuilderFactory->DocumentBuilder->Document->NsodeList之後就可以進行改變了
* @author SHUXIN
*/
public class DOM {
@Test
public void DOMfind() throws Exception{//進行查找元素的值
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
Document ducument = documentBuilder.parse("src/XML_Study/DOM_Study/DOM_Study.xml");
NodeList nodeList = ducument.getElementsByTagName("售價");
Node item1 = nodeList.item(1);
String name=item1.getTextContent();
System.out.println(name);
}
/**
* 把整個文件加載到內存之中,之後通過樹的結構進行操作
* DocumentBuilderFactory->DocumentBuilder->Document->NsodeList之後就可以進行改變內存了
* TransformerFactory->Transformer->newTransformer.transform(domsouce, outputTarget);//一個是Source一個接口,使用實現類DomSource,以及StreamResult
* @throws Exception
*/
@Test
public void modifDOM() throws Exception {//改變指定元素的內容
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
Document ducument = documentBuilder.parse("src/XML_Study/DOM_Study/DOM_Study.xml");
NodeList nodeList = ducument.getElementsByTagName("售價");
Node item1 = nodeList.item(1);
item1.setTextContent("2000");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer newTransformer = transformerFactory.newTransformer();
Source domsouce=new DOMSource(ducument);
Result outputTarget=new StreamResult("src/XML_Study/DOM_Study/DOM_Study.xml");
newTransformer.transform(domsouce, outputTarget);
}
}
2.SAX
SAX是一個解析速度快並且佔用內存少的xml解析器,非常適合用於Android等移動設備。SAX解析XML文件採用的是事件驅動,也就是說,它並不需要解析完整個文檔,在按內容順序解析文檔的過程中,SAX會判斷當前讀到的字符是否合法XML語法中的某部分,如果符合就會觸發事件。所謂事件,其實就是一些回調(callback)方法,這些方法(事件)定義在ContentHandler接口。
這種方式解析是一種基於事件驅動的api,有兩個部分,解析器和事件處理器:
解析器就是XMLReader接口,負責讀取XML文檔,和向事件處理器發送事件(也是事件源),
事件處理器ContentHandler接口,負責對發送的事件響應和進行XML文檔處理。對於SAX解析方式可以使用ContentHandle的實現類
以下是SAX的圖解,建議之後通過代碼對照理解
SAX常用事件如下:
startDocument() —-文檔開始事件
startElement() —-元素開始事件
characters() —-文本元素事件
endElement() —-元素結束事件
endDocument() —-文檔結束事件
XML文件同上
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<書架>
<書>
<名稱>平凡的世界</名稱>
<作者>路遙</作者>
<售價>50</售價>
</書>
<書>
<名稱>人生哲思錄</名稱>
<作者>周國平</作者>
<售價>2000</售價>
</書>
</書架>
JAVA代碼片,這邊只是使用了
characters() —-文本元素事件
endElement() —-元素結束事件
endDocument() —-文檔結束事件
package XML_Study.SAX_Study;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.Test;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
public class SAX_study {
/**
* sax解析基礎操作,大多數都是用handle來進行,重寫defaultHandle類中的方法來進行,原因是使用ContentHandle重寫的方法太多了
* 其他的東西都可以進行一系列的操作來進行
* @throws Exception
*/
@Test
public void SAXParserTest1() throws Exception{
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser newSAXParser = saxParserFactory.newSAXParser();
XMLReader reader=newSAXParser.getXMLReader();
reader.setContentHandler(new DefaultHandler(){
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)//遇到開始元素所做的工作
throws SAXException {
System.out.println("開始標籤"+qName);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {//遇到結束元素所做的工作
System.out.println("結束標籤"+qName);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {//遇到具體內容進行的操作
System.out.println(new String(ch,start,length));
}
});
reader.parse("src/XML_Study/SAX_Study/SAX_Study.xml");//開始解析
}
}
3、PULL
Pull解析器的運行方式與 SAX 解析器相似,都是輕量級的解析,在Android的內核中已經嵌入了Pull,所以我們不需要再添加第三方jar包來支持Pull。Android使用的就是pull進行解析所以pull顯得尤爲重要,但是pull和其他方式大同小異
如果是編寫java代碼就需要導入第三方的jar包
kxml2-2.3.0.jar和xmlpull_1_1_3_4c.jar版本沒有太大的關係
Pull解析和Sax解析不一樣的地方有:
- pull讀取xml文件後觸發相應的事件調用方法返回的是數字
- pull可以在程序中控制想解析到哪裏就可以停止解析。
方便參照將XML再貼一次
<?xml version="1.0" encoding="UTF-8" standalone="no"?><書架>
<書>
<名稱>平凡的世界</名稱>
<作者>路遙</作者>
<售價>50</售價>
</書>
<書>
<名稱>人生哲思錄</名稱>
<作者>周國平</作者>
<售價>2000</售價>
</書>
</書架>
在java代碼中使用了一個Book類,裏面只有Name,Author,Price三個變量以及對應的getter setter方法所以就不貼代碼了
package XML_Study.Pull_Study;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import com.sun.xml.internal.ws.api.pipe.NextAction;
import XML_Study.SAX_Study.Book;
public class PullParser_Study {
public ArrayList<Book> booklist = new ArrayList();
public boolean flag = false;
public Book book = new Book();
/**
* 使用了KXML 以及xmlpull包
* @throws Exception
*/
@Test
public void Pull_Study() throws Exception {
XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();
XmlPullParser newPullParser = xmlPullParserFactory.newPullParser();// 獲取解析器
newPullParser.setInput(new FileInputStream(new File("src/XML_Study/SAX_Study/SAX_Study.xml")), "UTF-8");// 第一個參數是輸入流,第二個參數是編碼格式
int EvenType = newPullParser.getEventType();//使用一個常量進行保存,我們得到的元素的類型
while (EvenType != XmlPullParser.END_DOCUMENT) {// 表示只要不是爲文件的末尾就可以了
switch (EvenType) {
case XmlPullParser.START_TAG://開始的元素
if (newPullParser.getName().equals("書")) {
book = new Book();
}
if (newPullParser.getName().equals("名稱")) {
book.setName(newPullParser.nextText());//使用nextText()函數得到內容
}
if (newPullParser.getName().equals("作者")) {
book.setAuthor(newPullParser.nextText());
}
if (newPullParser.getName().equals("售價")) {
book.setPrice(newPullParser.nextText());
}
case XmlPullParser.END_TAG://表示結束的元素
if (newPullParser.getName().equals("書架")) {
for(Book book:booklist )
System.out.println(book.getName()+" "+book.getAuthor()+" "+book.getPrice());
}if(newPullParser.getName().equals("書")){
booklist.add(book);
}
}
EvenType=newPullParser.nextTag();//切忌加上此行代碼,防止出現死循環
}
}
}