一、 前言
用 Java解析XML文檔,最常用的有兩種方法:使用基於事件的XML簡單API(Simple API for XML)稱爲SAX和基於樹和節點的文檔對象模型(Document Object Module)稱爲DOM。Sun公司提供了Java API for XML Parsing(JAXP)接口來使用SAX和DOM,通過JAXP,我們可以使用任何與JAXP兼容的XML解析器。
JAXP接口包含了三個包:
(1) org.w3c.dom W3C推薦的用於XML標準規劃文檔對象模型的接口。
(2) org.xml.sax 用於對XML進行語法分析的事件驅動的XML簡單API(SAX)
(3) javax.xml.parsers解析器工廠工具,程序員獲得並配置特殊的特殊語法分析器。
javax包 相對於 java包 佔用資源比較少
二、 前提
DOM編程不要其它的依賴包,因爲JDK裏自帶的JDK裏含有的上面提到的org.w3c.dom、org.xml.sax 和javax.xml.parsers包就可以滿意條件了。
三、 使用SAX解析XML文檔
SAX是基於事件的簡單API,同樣的我們也是用一個最簡單的例子來看看SAX是如何解析XML的
先來看看我們要解析的XML代碼吧
<?xml version="1.0" encoding="gb2312"?>
<books>
<book email=“alexlee”>
<name addr="address">kunshan</name>
<price>10</price>
</book>
</books>
簡單的不能再簡單了。但是該有的都有了,根元素、屬性、子節點。好了,能反應問題就行了,下面來看看解析這個XML文件的Java代碼吧!
這段代碼比較短,因爲SAX是事件驅動的,它的大部分實現在在另一個Java文件中,先別管另一個文件,我們來一個個地分析吧!
(1)得到SAX解析器的工廠實例
3 SAXParserFactory saxfac=SAXParserFactory.newInstance();
這是一個javax.xml.parsers.SAXParserFactory類的實例
(2)從SAX工廠實例中獲得SAX解析器
5 SAXParser saxparser=saxfac.newSAXParser();
使用javax.xml.parsers.SAXParserFactory工廠的newSAXParser()方法
(3)把要解析的XML文檔轉化爲輸入流,以便DOM解析器解析它
6 InputStream is=new FileInputStream("bin/library.xml");
InputStream是一個接口。
(4)解析XML文檔
7 saxparser.parse(is,new MySAXHandler());
後面就不用看了,都是些沒用的代碼(相對而言),夠簡單的吧!
注意了,我們新建了一個實例new MySAXHandler()這個實例裏面又有什麼東西呢?
這個實例就是SAX的精華所在。我們使用SAX解析器時,必須實現內容處理器ContentHandler接口中的一些回調方法,然而我們不須要全部地實現這些方法,還好,我們有org.xml.sax.helpers.DefaultHandler類,看它的類申明:
public class DefaultHandler
implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler
實現了這麼多接口啊,其它的先不管了,至少它實現了ContentHandler這一接口。
不要看它一大堆,我一一分解給大家看。我們說SAX是基於事件的API,我們這個類實到了ContentHandler接口中的如下方法:
(1)startDocument() 用於處理文檔解析開始事件
只被執行一次public void startDocument() throws SAXException {
System.out.println("文檔開始打印了");
}
(2)endDocument() 用於處理文檔解析結束事件
只被執行一次public void endDocument() throws SAXException {
System.out.println("文檔打印結束了");
}
(3)startElement 用於處理元素開始事件
遇到開始標籤被觸發public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(qName.equals("books")){
return;
}
if(qName.equals("book")){
System.out.println(attributes.getQName(0)+attributes.getValue(0));
}
if(attributes.getLength()>0){
this.attributes=attributes;
this.hasAttribute=true;
}
}
第二個參數String qName表示這個元素的名字,如:
根節點 <books></books> 它的qName爲“books”
最底層節點 <price>jjjjjj</price> 它的qName爲“price”
知道這一點上面程序就好解釋了,當遇到根元素“books”時就什麼也不做跳過,當遇到“book”元素時就打出它的屬性(它只有一個屬性<book email="zhoujunhui"></book>)。
當是其它節點時(這下只剩下最底層的兩個節點“name”和“price”了),就把它的屬性取出來存到this.attributes域中,以後中元素結束事件好處理。
(4)endElement 用於處理元素結束事件
遇到結束標籤被觸發public void endElement(String uri, String localName, String qName)
throws SAXException {
if(hasAttribute&&(attributes!=null)){
for(int i=0;i<attributes.getLength();i++){
System.out.println(attributes.getQName(0)+attributes.getValue(0));
}
}
}
代碼的作用是如果這個元素的屬性不爲空(hasAttribute&&(attributes!=null)),就把它們打印出來。
(5)characters(char[] ch, int start, int length) 處理元素字符的內容
<></> 之間遇到任何 "回車符" "空格符"或其他"不爲空"的字符都將觸發characters 方法,兩個標籤之間的部分,不論有多少
空格 回車 字符 都只能觸發一次characters方法
charachers(char [] ch,int start,int length):當遇到xml內容時觸發這個方法,
用new String(ch,start,length)可以接受內容
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.println(new String(ch,start,length));
}
public class SaxXml {
public static void main(String[] args) {
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
try {
SAXParser parser = saxFactory.newSAXParser();
File file = new File("src/com/xm/inproe.xml");
parser.parse(file, new MyHander());
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class MyHander extends DefaultHandler{
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String a = new String(ch, start, length);
System.out.print(a);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.print("</"+qName+">");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.print("<"+qName+"");
for (int i = 0; i < attributes.getLength(); i++) {
String name = attributes.getQName(i);
String values = attributes.getValue(name);
System.out.print(" "+name+"=“"+values+"”");
}
System.out.print(">");
}
}
inproe.xml
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="1" depName="教學部">
Text XMl sax
<name>tom</name>
<age>18</age>
<gender>male</gender>
<salary>200</salary>
<test>test</test>
</employee>
<employee id="2" depName="教學部">
<name>java</name>
<age>19</age>
<gender>famale</gender>
<salary>2050</salary>
</employee>
<employee id="3" depName="市場部">
<name>store</name>
<age>20</age>
<gender>famale</gender>
<salary>4000</salary>
</employee>
<employee id="4" depName="市場部">
<name>buy</name>
<age>21</age>
<gender>male</gender>
<salary>45500</salary>
</employee>
</employees>
控制檯輸出