一、技術概述 在用Java解析XML時候,一般都使用現成XML解析器來完成,自己編碼解析是一件很棘手的問題,對程式員要求很高,一般也沒有專業廠商或者開源組織實作的好。 Java解析XML的原理圖如下: 目前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解析器。但并不是所有的Java XML解析工具都實作了SUN提供的接口。DOM4J就沒有遵循SUN的JAXP規範,但非常優秀。 DOM 采用建立樹形結構的方式通路 XML 文檔,而 SAX 采用的事件模型。 DOM 是W3C組織推薦的處理XML的标準接口,DOM 解析器把 XML 文檔轉化為一個包含其内容的樹,并可以對樹進行周遊。用 DOM 解析模型的優點是程式設計容易,開發人員隻需要調用建樹的指令,然後利用navigation APIs通路所需的樹節點來完成任務。可以很容易的添加和修改樹中的元素。然而由于使用 DOM 解析器的時候需要處理整個 XML 文檔,是以對性能和記憶體的要求比較高,尤其是遇到很大的 XML 檔案的時候。由于它的周遊能力,DOM 解析器常用于 XML 文檔需要頻繁的改變的服務中。 SAX是由XML_DEV郵件清單的成員開發的,它不是某個官方機構的标準,也不由W3C組織或其他任何官方機構維護,但它是XML社群事實上的标準。雖然SAX隻是“民間”标準,但是它在XML中的應用絲毫不比DOM少,幾乎所有的XML解析器都支援它。SAX 解析器采用了基于事件的模型,它在解析 XML 文檔的時候可以觸發一系列的事件,當發現給定的tag的時候,它可以激活一個回調方法,告訴該方法制定的标簽已經找到。SAX 對記憶體的要求通常會比較低,因為它讓開發人員自己來決定所要處理的tag。特别是當開發人員隻需要處理文檔中所包含的部分資料時,SAX 這種擴充能力得到了更好的展現。但用 SAX 解析器的時候編碼工作會比較困難,而且很難同時通路同一個文檔中的多處不同資料。 DOM和SAX隻是定義了一些接口,以及某些接口的預設實作,一個應用程式要想利用DOM或SAX通路XML文檔,還需要一個實作了DOM或SAX的解析器(實作DOM和SAX中定義的接口,提供DOM和SAX定義的功能)。 Apache的Xerces是一個使用非常廣泛的解析其,它提供了DOM和SAX的調用接口,并有多種語言的實作版本,要利用Xerces通路XML文檔,隻需要在應用程式中構造一個解析器實作類的對象。 這裡面還存在一個問題,雖然使用的是标準的DOM和SAX接口,由于不同的XML解析器的實作類是不同的,如果使用另外一種解析器,仍然需要修改應用程式,隻不過修改的代碼量較小,需要更改XML解析器實作類的類名,然後重新編譯、釋出。 然而,對于相容JAXP的XML解析器,我們可以選用JAXP API,這樣在更換相容JAXP解析器的時候,就不用對已釋出的程式做任何的改動。 JAXP開發包由javax.xml包、org.w3c.dom包、org.xml.sax包及其子包組成。在javax.xml.parsers包中,定義了幾個工廠類,用于加載DOM和SAX的實作類。 使用JAXP API解析XML的原理如下: 二、使用DOM解析XML DOM的核心概念就是NODE(節點)。DOM在分析XML文檔時,将組成XML文檔的各個部分(元素,屬性,文本,注釋,處理指令等)映射成一個對象,這個對象就叫做節點。在記憶體中這些節點形成一棵樹。整棵樹就是一個節點,樹中的每一個節點也是一棵樹(子樹)。DOM就是對這棵樹的一個對象描述,我們通過通路樹中的節點來存取XML文檔的内容。 DOM定義了一個Node接口,用于表示文檔樹中一個節點。從這個接口派生出來更多的具體的接口。例如,表示整個文檔的Document接口,表示XML文檔中的一個元素的Element接口,表示元素屬性的Attr接口,都是從Node接口派生而來的。在org.w3c.dom包中,表示XML文檔各組成部分的接口的繼承關系如圖: 舉個例子,引用java web開發大全,有改動: students.xml ----------------------------------------------------------------------
張三
18
李四
20
---------------------------------------------------------------------- public class DOMStudentsInfo {
public static void main(String[] args) {
//擷取生成 DOM 對象樹的解析器
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try {
//從 DocumentBuilderFactory擷取 DocumentBuilder執行個體
DocumentBuilder db = dbf.newDocumentBuilder();
File file = new File(\"students.xml\");
從 XML 文檔擷取 DOM 文檔執行個體
Document doc = db.parse(file); //擷取某節點的集合
NodeList nl = doc.getElementsByTagName(\"student\"); int len = nl.getLength();
for (int i = 0; i < len; i++) {
Element eltStu = (Element) nl.item(i);
Node eltName = eltStu.getElementsByTagName(\"name\").item(0);
Node eltAge = eltStu.getElementsByTagName(\"age\").item(0); String name = eltName.getFirstChild().getNodeValue();
String age = eltAge.getFirstChild().getNodeValue(); System.out.print(\"姓名:\");
System.out.println(name); System.out.print(\"年齡:\");
System.out.println(age);
System.out.println(\"----------------------------\\n\");
}
}
catch (ParserConfigurationException e) {
e.printStackTrace();
}
catch (SAXException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
運作結果:
a1234
四川省xx縣xx鎮xx路x段xx号
b1234
四川省xx市xx鄉xx村xx組
---------------------------------------------------------------------- public class MyXMLReader2 extends DefaultHandler {
java.util.Stack tags = new java.util.Stack(); public MyXMLReader2() {
super();
} public static void main(String args[]) {
long lasting = System.currentTimeMillis();
try {
SAXParserFactory sf = SAXParserFactory.newInstance();
SAXParser sp = sf.newSAXParser();
MyXMLReader2 reader = new MyXMLReader2();
sp.parse(new InputSource(\"data_10k.xml\"), reader);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(\"運作時間:\" + (System.currentTimeMillis() - lasting) + \" 毫秒\");
} public void characters(char ch[], int start, int length) throws SAXException {
String tag = (String) tags.peek();
if (tag.equals(\"no\")) {
System.out.print(\"車牌号碼:\" + new String(ch, start, length));
}
if (tag.equals(\"addr\")) {
System.out.println(\" 位址:\" + new String(ch, start, length));
}
} public void startElement(
String uri,
String localName,
String qName,
Attributes attrs) {
tags.push(qName);
}
} 運作結果: SAXReader reader = new SAXReader();
Document doc = reader.read(f);
Element root = doc.getRootElement();
Element foo;
for (Iterator i = root.elementIterator(\"value\"); i.hasNext();) {
foo = (Element) i.next();
System.out.print(\"車牌号碼:\" + foo.elementText(\"no\"));
System.out.println(\" 車主位址:\" + foo.elementText(\"addr\"));
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(\"運作時間:\" + (System.currentTimeMillis() - lasting) + \" 毫秒\");
}
} 五、使用JDOM解析xml public class MyXMLReader3 {
public static void main(String arge[]) {
long lasting = System.currentTimeMillis();
try {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new File(\"data_10k.xml\"));
Element foo = doc.getRootElement();
List allChildren = foo.getChildren();
for (int i = 0; i < allChildren.size(); i++) {
System.out.print(\"車牌号碼:\" + ((Element) allChildren.get(i)).getChild(\"no\").getText());
System.out.println(\" 車主位址:\" + ((Element) allChildren.get(i)).getChild(\"addr\").getText());
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(\"運作時間:\" + (System.currentTimeMillis() - lasting) + \" 毫秒\");
}
}
六、使用JAXP解析XML public class MyXMLReader1 {
public static void main(String arge[]) {
long lasting = System.currentTimeMillis();
try {
File f = new File(\"data_10k.xml\");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(f);
NodeList nl = doc.getElementsByTagName(\"value\");
for (int i = 0; i < nl.getLength(); i++) {
System.out.print(\"車牌号碼:\" + doc.getElementsByTagName(\"no\").item(i).getFirstChild().getNodeValue());
System.out.println(\" 車主位址:\" + doc.getElementsByTagName(\"addr\").item(i).getFirstChild().getNodeValue());
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(\"運作時間:\" + (System.currentTimeMillis() - lasting) + \" 毫秒\");
}
}