Java中應用DOM和SAX解析XML文件的辦法示例。本站提示廣大學習愛好者:(Java中應用DOM和SAX解析XML文件的辦法示例)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中應用DOM和SAX解析XML文件的辦法示例正文
dom4j引見
dom4j的項目地址:http://sourceforge.net/projects/dom4j/?source=directory
dom4j是一個簡略的開源庫,用於處置XML、 XPath和XSLT,它基於Java平台,應用Java的聚集框架,周全集成了DOM,SAX和JAXP。
dom4j的應用
下載了dom4j項目以後,解緊縮,將其jar包(我確當前版本叫做dom4j-1.6.1.jar)參加class path上面。
(Properties->Java Build Path -> Add External JARs...)。
以後便可以應用其供給的API停止編程。
法式實例1
第一個法式,用Java代碼生成xml文檔,代碼以下:
package com.example.xml.dom4j;
import java.io.FileOutputStream;
import java.io.FileWriter;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
/**
* dom4j框架進修 應用dom4j框架創立xml文檔並輸入保留
*
*/
public class Dom4JTest1
{
public static void main(String[] args) throws Exception
{
// 第一種方法:創立文檔,並創立根元素
// 創立文檔:應用了一個Helper類
Document document = DocumentHelper.createDocument();
// 創立根節點並添加進文檔
Element root = DocumentHelper.createElement("student");
document.setRootElement(root);
// 第二種方法:創立文檔並設置文檔的根元素節點
Element root2 = DocumentHelper.createElement("student");
Document document2 = DocumentHelper.createDocument(root2);
// 添加屬性
root2.addAttribute("name", "zhangsan");
// 添加子節點:add以後就前往這個元素
Element helloElement = root2.addElement("hello");
Element worldElement = root2.addElement("world");
helloElement.setText("hello Text");
worldElement.setText("world text");
// 輸入
// 輸入到掌握台
XMLWriter xmlWriter = new XMLWriter();
xmlWriter.write(document);
// 輸入到文件
// 格局
OutputFormat format = new OutputFormat(" ", true);// 設置縮進為4個空格,而且另起一行動true
XMLWriter xmlWriter2 = new XMLWriter(
new FileOutputStream("student.xml"), format);
xmlWriter2.write(document2);
// 另外一種輸入方法,記得要挪用flush()辦法,不然輸入的文件中顯示空白
XMLWriter xmlWriter3 = new XMLWriter(new FileWriter("student2.xml"),
format);
xmlWriter3.write(document2);
xmlWriter3.flush();
// close()辦法也能夠
}
}
法式Console輸入:
<?xml version="1.0" encoding="UTF-8"?> <student/>
生成的一個xml文檔:
<?xml version="1.0" encoding="UTF-8"?> <student name="zhangsan"> <hello>hello Text</hello> <world>world text</world> </student>
法式實例2
法式實例2,讀入xml文檔並剖析,將其內容輸入。
起首,待剖析的文檔以下:
<?xml version="1.0" encoding="UTF-8"?>
<students name="zhangsan">
<hello name="lisi">hello Text1</hello>
<hello name="lisi2">hello Text2</hello>
<hello name="lisi3">hello Text3</hello>
<world name="wangwu">world text1</world>
<world name="wangwu2">world text2</world>
<world >world text3</world>
</students>
package com.example.xml.dom4j;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.DOMReader;
import org.dom4j.io.SAXReader;
/**
* dom4j框架進修: 讀取並解析xml
*
*
*/
public class Dom4JTest2
{
public static void main(String[] args) throws Exception
{
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("students.xml"));
// 獲得根元素
Element root = document.getRootElement();
System.out.println("Root: " + root.getName());
// 獲得一切子元素
List<Element> childList = root.elements();
System.out.println("total child count: " + childList.size());
// 獲得特命名稱的子元素
List<Element> childList2 = root.elements("hello");
System.out.println("hello child: " + childList2.size());
// 獲得名字為指命名稱的第一個子元素
Element firstWorldElement = root.element("world");
// 輸入其屬性
System.out.println("first World Attr: "
+ firstWorldElement.attribute(0).getName() + "="
+ firstWorldElement.attributeValue("name"));
System.out.println("迭代輸入-----------------------");
// 迭代輸入
for (Iterator iter = root.elementIterator(); iter.hasNext();)
{
Element e = (Element) iter.next();
System.out.println(e.attributeValue("name"));
}
System.out.println("用DOMReader-----------------------");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// 留意要用完全類名
org.w3c.dom.Document document2 = db.parse(new File("students.xml "));
DOMReader domReader = new DOMReader();
// 將JAXP的Document轉換為dom4j的Document
Document document3 = domReader.read(document2);
Element rootElement = document3.getRootElement();
System.out.println("Root: " + rootElement.getName());
}
}
代碼運轉後輸入:
Root: students total child count: 6 hello child: 3 first World Attr: name=wangwu 迭代輸入----------------------- lisi lisi2 lisi3 wangwu wangwu2 null 用DOMReader----------------------- Root: students
SAX解析XML
上面是SAX完成實體解析的步調
//上面應用XMLReader 來解析
(一)第一步:新建一個工場類SAXParserFactory,代碼以下:
SAXParserFactory factory = SAXParserFactory.newInstance();
(二)第二步:讓工場類發生一個SAX的解析類SAXParser,代碼以下:
SAXParser parser = factory.newSAXParser();
(三)第三步:從SAXPsrser中獲得一個XMLReader實例,代碼以下:
XMLReader reader = parser.getXMLReader();
(四)第四步:把本身寫的handler注冊到XMLReader中,普通最主要的就是ContentHandler,代碼以下:
reader.setContentHandler(this);
(五)第五步:將一個xml文檔或許資本釀成一個java可以處置的InputStream流後,解析正式開端,代碼以下:
reader.parse(new InputSource(is));
//上面應用SAXParser來解析
(一)第一步:新建一個工場類SAXParserFactory,代碼以下:
SAXParserFactory factory = SAXParserFactory.newInstance();
(二)第二步:讓工場類發生一個SAX的解析類SAXParser,代碼以下:
SAXParser parser = factory.newSAXParser();
(三)第三步:將一個xml文檔或許資本釀成一個java可以處置的InputStream流後,解析正式開端,代碼以下:
parser.parse(is,this);
估量年夜家都看到了ContentHandler ,上面詳細的講下
解析開端之前,須要向XMLReader/SAXParser 注冊一個ContentHandler,也就是相當於一個事宜監聽器,在ContentHandler中界說了許多辦法
//設置一個可以定位文檔內容事宜產生地位的定位器對象
public void setDocumentLocator(Locator locator)
//用於處置文檔解析開端事宜
public void startDocument()throws SAXException
//處置元素開端事宜,從參數中可以取得元素地點稱號空間的uri,元素稱號,屬性類表等信息
public void startElement(String namespacesURI , String localName , String qName , Attributes atts) throws SAXException
//處置元素停止事宜,從參數中可以取得元素地點稱號空間的uri,元素稱號等信息
public void endElement(String namespacesURI , String localName , String qName) throws SAXException
//處置元素的字符內容,從參數中可以取得內容
public void characters(char[] ch , int start , int length) throws SAXException
趁便引見下XMLReader中的辦法。
//注冊處置XML文檔解析事宜ContentHandler
public void setContentHandler(ContentHandler handler)
//開端解析一個XML文檔
public void parse(InputSorce input) throws SAXException
年夜概的講的差不多了 接上去開端講授解析的步調
我們照樣用上一章的代碼
起首 我們創立一個Person類 用來存儲用戶的信息
package com.example.demo;
import java.io.Serializable;
public class Person implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String _id;
private String _name;
private String _age;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String get_name() {
return _name;
}
public void set_name(String _name) {
this._name = _name;
}
public String get_age() {
return _age;
}
public void set_age(String _age) {
this._age = _age;
}
}
接上去 我們要完成一個ContentHandler 用來解析XML
完成一個ContentHandler 普通須要上面幾個步調
1、聲明一個類,繼續DefaultHandler。DefaultHandler是一個基類,這個類外面簡略完成了一個ContentHandler。我們只須要重寫外面的辦法便可。
2、重寫 startDocument() 和 endDocument(),普通將正式解析之前的初始化放到startDocument()外面,掃尾的任務放到endDocument()外面。
3、重寫startElement(),XML解析器碰到XML外面的tag時就會挪用這個函數。常常在這個函數內是經由過程對localName的值停止斷定而操作一些數據。
4、重寫characters()辦法,這是一個回調辦法。解析器履行完startElement()後,解析節點的內容後就會履行這個辦法,而且參數ch[]就是節點的內容。
5、重寫endElement()辦法,這個辦法與startElement()絕對應,解析完一個tag節點後,履行這個辦法,解析一個tag後,挪用這個處置復原和消除相干信息
起首 新建一個類 繼續DefaultHandler 偏重寫以下幾個辦法
public class SAX_parserXML extends DefaultHandler {
/**
* 當開端解析xml文件的聲明的時刻就會觸發這個事宜, 可以做一些初始化的任務
* */
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
}
/**
* 當開端解析元素的開端標簽的時刻,就會觸發這個事宜
* */
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
}
/**
* 當讀到文本元素的時刻要觸發這個事宜.
* */
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
}
/**
* 當讀到停止標簽的時刻 就會觸發這個事宜
* */
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
}
}
起首 我們創立一個list 用來保留解析出來的person數據
List<Person> persons;
然則?在哪裡初始化呢?我們可以在startDocument()外面初始化,由於當開端解析xml文件的聲明的時刻就會觸發這個事宜所以放在這裡比擬適合
/**
* 當開端解析xml文件的聲明的時刻就會觸發這個事宜, 可以做一些初始化的任務
* */
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
// 初始化list
persons = new ArrayList<Person>();
}
接上去 就要開端解析了
/**
* 當開端解析元素的開端標簽的時刻,就會觸發這個事宜
* */
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
// 假如讀到是person標簽 開端存儲
if (localName.equals("person")) {
person = new Person();
person.set_id(attributes.getValue("id"));
}
curNode = localName;
}
下面的代碼中 localName表現以後解析到的元素名
//步調
//1.斷定能否是person元素
//2.創立新的Person對象
//3.獲得id 添加到Person對象中
curNode 用來保留以後的元素名 在characters中會應用到
/**
* 當讀到文本元素的時刻要觸發這個事宜.
* */
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
if (person != null) {
//掏出今朝元素對應的值
String txt = new String(ch, start, length);
//斷定元素能否是name
if (curNode.equals("name")) {
//將掏出的值添加到person對象
person.set_name(txt);
} else if (curNode.equals("age")) {
person.set_age(txt);
}
}
}
接上去是引見標簽停止的時刻須要做的工作
/**
* 當讀到停止標簽的時刻 就會觸發這個事宜
* */
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
// 假如是 而且person不為空,添加到list
if (localName.equals("person") && person != null) {
persons.add(person);
person = null;
}
curNode = "";
}
解析的工作停止了 年夜概流程就是
1.一個元素開端時 會挪用startElement辦法
2.接上去會挪用到characters辦法,可以用來獲得元素的值
3.一個元素停止時 會挪用到endElement辦法
解析停止以後 我們須要寫一個辦法 用來獲得解析後保留的list
public List<Person> ReadXML(InputStream is) {
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
// 第一種辦法
// parser.parse(is, this);
// 第二種辦法
XMLReader reader = parser.getXMLReader();
reader.setContentHandler(this);
reader.parse(new InputSource(is));
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return persons;
}
下面的代碼就不說明了 只需將inputStream對象傳入 便可以解析出內容
看完了代碼,我來給出完全的代碼
package com.example.demo.Utils;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import com.example.demo.Person;
public class SAX_parserXML extends DefaultHandler {
List<Person> persons;
Person person;
// 以後節點
String curNode;
public List<Person> ReadXML(InputStream is) {
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
// 第一種辦法
// parser.parse(is, this);
// 第二種辦法
XMLReader reader = parser.getXMLReader();
reader.setContentHandler(this);
reader.parse(new InputSource(is));
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return persons;
}
/**
* 當開端解析xml文件的聲明的時刻就會觸發這個事宜, 可以做一些初始化的任務
* */
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
// 初始化list
persons = new ArrayList<Person>();
}
/**
* 當開端解析元素的開端標簽的時刻,就會觸發這個事宜
* */
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
// 假如讀到是person標簽 開端存儲
if (localName.equals("person")) {
person = new Person();
person.set_id(attributes.getValue("id"));
}
curNode = localName;
}
/**
* 當讀到文本元素的時刻要觸發這個事宜.
* */
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
if (person != null) {
// 掏出今朝元素對應的值
String txt = new String(ch, start, length);
// 斷定元素能否是name
if (curNode.equals("name")) {
// 將掏出的值添加到person對象
person.set_name(txt);
} else if (curNode.equals("age")) {
person.set_age(txt);
}
}
}
/**
* 當讀到停止標簽的時刻 就會觸發這個事宜
* */
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
// 假如是person開頭 而且person不為空,添加到list
if (localName.equals("person") && person != null) {
persons.add(person);
person = null;
}
curNode = "";
}
}
寫個辦法挪用下這個類
List<Person> persons = new SAX_parserXML().ReadXML(is);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < persons.size(); i++) {
Person person =persons.get(i);
buffer.append("id:" + person.get_id() + " ");
buffer.append("name:" + person.get_name() + " ");
buffer.append("age:" + person.get_age() + "\n");
}
Toast.makeText(activity, buffer, Toast.LENGTH_LONG).show();
假如你看到上面的界面 解釋解析勝利了~
小結:
DOM(文件對象模子)解析:解析器讀入全部文檔,然後構建一個駐留內存的樹構造,然子女碼便可以依據DOM接口來操作這個樹構造了。
長處:全部文檔讀入內存,便利操作:支撐修正、刪除和重現分列等多種功效。
缺陷:將全部文檔讀入內存中,保存了過量的不須要的節點,糟蹋內存和空間。
應用場所:一旦讀入文檔,還須要屢次對文檔停止操作,而且在硬件資本充分的情形下(內存,CPU)。
為懂得決DOM解析存在的成績,就湧現了SAX解析。其特色為:
長處:不消完成調入全部文檔,占用資本少。特別在嵌入式情況中,如android,死力推舉應用SAX解析。
缺陷:不像DOM解析一樣將文檔歷久駐留在內存中,數據不是耐久的。假如事宜事後沒有保留數據,數據就會喪失。
應用場所:機械有機能限制