本實例解析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(); } } }
全站熱搜
留言列表