本實例解析xml使用的是繼承DefaultHandler類,此類就是java中封裝好的xml解析器類,下面看代碼詳細說明:

 

第一步:首先說明下xml文件,Java Sax解析是按照xml文件的順序一步一步的來解析,在解析xml文件之前,我們要先了解xml文件的節點的種類,一種是ElementNode,一種是TextNode。如下面的這段people.xml,其中,像<people>、<person>這種節點就屬於ElementNode,而張三這種就屬於TextNode,001屬於Attributes的值

 

 

<?xml version="1.0" encoding="UTF-8"?>
<people> 
  <person personid="001"> 
    <name>張三</name> 
    <tel>12345</tel> 
  </person> 
    
  <person personid="002"> 
    <name>李四</name> 
    <tel>678910</tel> 
  </person> 
</people> 

 

 

第二步:我們为了代碼的复用性高點我們先繼承DefaultHandler創建一個BaseHandler基礎的解析器抽象類,詳細說明和代碼如下:

 

 

import java.io.File;
import java.io.InputStream;
import java.io.StringReader;
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;
public abstract class BaseHandler extends DefaultHandler {
// 解析時導入的是xml字符串
public boolean parse(String xmlString) {
return false;
};
// 解析時導入的是xml流
public boolean parse(InputStream xmlInputStream) {
return false;
};
// 解析時導入的是xml的File類型數據
public boolean parse(File file) {
return false;
};
public void parserXml(BaseHandler baseHandler, String xmlString)
throws Exception {
if (xmlString == null || xmlString.length() == 0)
return;
//注冊baseHandler事件並獲取XMLReader實例
XMLReader xmlReader = xmlReader(baseHandler);
//將字符串轉換成StringReader對象
StringReader read = new StringReader(xmlString);
//將字StringReader對象轉換成InputSource對象
InputSource source = new InputSource(read);
//將一個xml字符串變成一個java可以處理的InputSource對象載入xmlReader的parse方法中,解析正式開始
xmlReader.parse(source);
read.close();
}
//把自己寫的baseHandler注冊到XMLReader中並返回XMLReader對象
private XMLReader xmlReader(BaseHandler baseHandler) {
//獲得解析工廠的實例 
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser;
XMLReader xmlReader = null;
try {
//獲得工廠解析器  
parser = factory.newSAXParser();
//從SAXPsrser中得到一個XMLReader實例
xmlReader = parser.getXMLReader();
//把自己寫的baseHandler注冊到XMLReader中(注冊處理XML文檔解析事件ContentHandler)
xmlReader.setContentHandler(baseHandler);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return xmlReader;
}
public void parserXml(BaseHandler baseHandler,
InputStream xmlInputStream) throws Exception {
if (xmlInputStream == null)
return;
//獲得解析工廠的實例 
SAXParserFactory factory = SAXParserFactory.newInstance();
//獲得工廠解析器  
SAXParser parser = factory.newSAXParser();
//將一個xml流載入parse方法中,解析正式開始
parser.parse(xmlInputStream, baseHandler);
}
public void parserXml(BaseHandler baseHandler,
File file) throws Exception {
if (file == null)
return;
//獲得解析工廠的實例 
SAXParserFactory factory = SAXParserFactory.newInstance();
//獲得工廠解析器  
SAXParser parser = factory.newSAXParser();
//將一個xml文件對象File載入parse方法中,解析正式開始
parser.parse(file, baseHandler);
}
/*
 * 讀取標簽裏的值,ch用來存放某行的xml的字符數據,包括標簽,初始大小是2048, 每解釋到新的字符會把它添加到char[]裏。 *
 * 注意,這個char字符會自己管理存儲的字符, 並不是每一行就會刷新一次char,start,length是由xml的元素數據確定的,
 * 這裏一個正標簽,反標簽都會被執行一次characters,所以在反標簽時不用獲得其中的值
 * 這裏獲取的值是標簽之間的值如:<item>*********</item>表示星號部分的值
 */
public abstract void characters(char[] ch, int start, int length)
throws SAXException;
// 用戶處理文檔解析結束事件
public void endDocument() throws SAXException{};
// 用於處理元素結束事件
public abstract void endElement(String uri, String localName, String qName)
throws SAXException;
// 用於處理文檔解析開始事件
public void startDocument() throws SAXException{};
/*
 * 用於處理元素開始事件, 
 * 在解釋到一個開始元素時會調用此方法.但是當元素有重复時可以自己寫算法來區分 這些重复的元素.qName是什麼?
 * <name:page ll=""></name:page>這样寫就會拋出SAXException錯誤 通常情況下qName等於localName
 */
public abstract void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException;
}

 

 

第三步:我們針對自己編寫的people.xml文件作为本例解析文件做一個對應的PeopleHandler類繼承基礎類BaseHandler,實現如下:

 

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
public class PeopleHandler extends BaseHandler {
private Person mPerson;
//實例化一個棧用於存放標簽
private Stack<String> tagStack = new Stack<String>();
//實例化一個集合存儲Person對象
private List<Person> list = new ArrayList<Person>();
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String chars = new String(ch, start, length).trim();
if (chars != null) {
String tagName = (String) tagStack.peek();//從棧中獲取一個標簽元素
if (tagName.equals("name")) {
mPerson.setName(chars);
} else if (tagName.equals("tel")) {
mPerson.setTel(chars);
}
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
tagStack.pop();//當一個標簽把他彈出棧
if (qName.equals("person")) {//當一個person標簽結束時將mPerson對象添加到list集合中
list.add(mPerson);
}
}
@Override
public boolean parse(String xmlString) {
try {
super.parserXml(this, xmlString);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean parse(InputStream xmlInputStream) {
try {
super.parserXml(this, xmlInputStream);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean parse(File file) {
try {
super.parserXml(this, file);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equals("person")) {//當一個person標簽開始時實例化一個Person對象
mPerson = new Person();
String personId = attributes.getValue("personid");//獲取person標簽中的屬性值personId
mPerson.setPersonID(personId);
} 
tagStack.push(qName);
}
public List<Person> getResult(){
return list;
}
public void clear(){
list.clear();
}
}

 

 

第四步:編寫一個測試類main進行測試驗證:

 

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Mian {
public static void main(String[] args) {
// 實例化自定義的解析類
PeopleHandler mHandler = new PeopleHandler();
// 載入解析對象這裏使用三種方式
// 第一種:載入xml的File類型進行解析
String filename = "src/people.xml";
File file = new File(filename);
mHandler.parse(file);
System.out.println("第一種方式實現輸出結果:" + mHandler.getResult());
mHandler.clear();
// 第二種:載入xml流的方式進行解析
try {
InputStream is = new FileInputStream(file);
mHandler.parse(is);
System.out.println("第二種方式實現輸出結果:" + mHandler.getResult());
mHandler.clear();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 第三種:載入xml字符串的方式進行解析
try {
InputStreamReader insReader = new InputStreamReader(
new FileInputStream(file), "UTF-8");
BufferedReader bufReader = new BufferedReader(insReader);
StringBuffer str = new StringBuffer();
String line;
while ((line = bufReader.readLine()) != null) {
str.append(line);
}
bufReader.close();
insReader.close();
mHandler.parse(str.toString());
System.out.println("第三種方式實現輸出結果:" + mHandler.getResult());
mHandler.clear();
} catch (IOException e) {
e.getStackTrace();
}
}
}

 

arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()