關於本課程的視頻課程地址:http://edu.51cto.com/course/15238.htmlhtml
dom、sax、jdom、dom4jjava
Document Object Model,在應用程序中,基於DOM的XML分析器將一個XML文檔轉換成一個對象模型的集合(一般稱DOM樹),應用程序經過對這個對象模型的操做,來實現對XML文檔數據的操做。node
經過DOM接口,應用程序能夠在任什麼時候候訪問XML文檔中的任何一部分數據,所以,這種利用DOM接口的機制也被稱做隨機訪問機制。程序員
DOM樹所提供的隨機訪問方式給應用程序的開發帶來了很大的靈活性,它能夠任意地控制整個XML文檔中的內容。編程
然而,因爲DOM分析器把整個XML文檔轉化成DOM樹放在了內存中,所以,當文檔比較大或結構比較複雜時,對內存的需求就比較高。並且,對於結構複雜的樹的遍歷也是一項耗時的操做。因此,DOM分析器對機器性能的要求比較高,實現效率不十分理想。api
因爲DOM分析器所採用的樹結構的思想與XML文檔的結構相吻合,同時鑑於隨機訪問所帶來的方便,所以,DOM分析器仍是有很普遍的應用價值的。app
對於XML應用開發來講,DOM就是一個對象化的XML數據接口,一個與語言無關、與平臺無關的標準接口規範。
DOM定義了HTML文檔和XML文檔的邏輯結構,給出了一種訪問和處理這兩種文檔的方法。文檔表明的是數據,而DOM則表明瞭如何去處理這些數據。
做爲W3C的標準接口規範,目前,DOM由三部分組成,包括:核心(core)、HTML接口和XML接口。
核心部分是結構化文檔比較底層對象的集合,這一部分所定義的對象已經徹底能夠表達出任何HTML和XML文檔中的數據了。
HTML接口和XML接口兩部分則是專爲操做具體HTML文檔和XML文檔所提供的高級接口。框架
<?xml version="1.0" encoding="UTF-8"?> <student id="s01"> <sname>關羽</sname> <addr>南京</addr> </student>
對應內存中的dom樹dom
最多見的節點類型:ide
元素:元素是XML的基本構建。
元素能夠有其餘元素、文本節點或二者兼有來做爲其子節點。
元素節點仍是能夠有屬性的惟一類型的節點。
屬性:屬性節點包含關於元素節點的信息,但實際上,不認爲它是元素的子節點。
文本:確切來說,文本節點是文本。它能夠包含許多信息或僅僅是空白。
文檔(根節點) :文檔節點是整個文檔中全部其餘節點的父節點。(根節點不等於根元素節點)。
較不常見的節點類型:CDATA、註釋、處理指令。
Node、Document、NodeList接口、NamedNodeMap、Element
node接口
The Node interface is the primary datatype for the entire Document Object Model. It represents a single node in the document tree. While all objects implementing the Node interface expose methods for dealing with children, not all objects implementing the Node interface may have children. For example, Text nodes may not have children, and adding children to such nodes results in a DOMException being raised. The attributes nodeName, nodeValue and attributes are included as a mechanism to get at node information without casting down to the specific derived interface. In cases where there is no obvious mapping of these attributes for a specific nodeType (e.g., nodeValue for an Element or attributes for a Comment ), this returns null. Note that the specialized interfaces may contain additional and more convenient mechanisms to get and set the relevant information.
Document
The Document interface represents the entire HTML or XML document. Conceptually, it is the root of the document tree, and provides the primary access to the document's data. Since elements, text nodes, comments, processing instructions, etc. cannot exist outside the context of a Document, the Document interface also contains the factory methods needed to create these objects. The Node objects created have a ownerDocument attribute which associates them with the Document within whose context they were created.
NodeList
The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live. The items in the NodeList are accessible via an integral index, starting from 0.
getLength() :得到集合的長度
Node item(int index):得到指定索引的節點
NamedNodeMap
public interface NamedNodeMap Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes. NamedNodeMap objects in the DOM are live.
Element
The Element interface represents an element in an HTML or XML document. Elements may have attributes associated with them; since the Element interface inherits from Node, the generic Node interface attribute attributes may be used to retrieve the set of all attributes for an element. There are methods on the Element interface to retrieve either an Attr object by name or an attribute value by name. In XML, where an attribute value may contain entity references, an Attr object should be retrieved to examine the possibly fairly complex sub-tree representing the attribute value. On the other hand, in HTML, where all attributes have simple string values, methods to directly access an attribute value can safely be used as a convenience.
首先若是想要解析xml文件,必須得到到Document對象
DocumentBuilder類(抽象類):[DocumentBuilderFactory.newDocumentBuilder()
]() 來獲取此類的對象
DocumentBuilderFactory(抽象類):產生DocumentBuilder類的對象,這個類提供了一個靜態的方法能夠產生本身的實例
案例1:
package cn.org.kingdom.dom; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class DomParserDemo01 { public static void main(String[] args) throws ParserConfigurationException, FileNotFoundException, SAXException, IOException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new FileInputStream("src"+File.separator+"demo01.xml")); Element el = doc.getDocumentElement(); System.out.println("節點的名字:"+el.getNodeName()); System.out.println("節點的值:"+el.getNodeValue()); System.out.println("節點的類型:"+el.getNodeType()); System.out.println("============================="); Attr attr = el.getAttributeNode("id"); System.out.println("屬性的名字:"+attr.getName()); System.out.println("屬性的值:"+attr.getValue()); System.out.println("屬性的類型:"+attr.getNodeType()); System.out.println("============================="); //得到根節點的全部子節點 NodeList nl = el.getChildNodes(); System.out.println("子節點的數量:"+nl.getLength()); for(int i = 0 ;i<nl.getLength();i++) { Node n = nl.item(i); //屏蔽掉文本節點 //System.out.println(n.getNodeName()+"-->"+n.getNodeType()); if(n.getNodeType()==1) { System.out.println(n.getLastChild().getNodeValue()); } } } }
案例2:
package cn.org.kingdom.dom; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.SAXException; public class DomParseDemo02 { public static void main(String[] args) throws ParserConfigurationException, FileNotFoundException, SAXException, IOException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new FileInputStream("src"+File.separator+"demo01.xml")); Element el = doc.getDocumentElement(); NamedNodeMap nnm = el.getAttributes(); int length = nnm.getLength(); System.out.println("el元素中擁有的屬性數量爲:"+length); for(int i = 0 ;i<nnm.getLength();i++) { Attr n = (Attr) nnm.item(i); System.out.println(n.getNodeName()+"-->"+n.getNodeValue()); } Element el_sname=(Element) el.getElementsByTagName("sname").item(0); System.out.println(el_sname.getNodeName()+"-->"+el_sname.getFirstChild().getNodeValue()); Element el_add = (Element) el_sname.getNextSibling().getNextSibling(); System.out.println(el_add.getNodeName()+"-->"+el_add.getFirstChild().getNodeValue()); System.out.println(el_add.getParentNode().getNodeName()); System.out.println(doc.getXmlEncoding()); System.out.println(doc.getXmlVersion()); } }
•TransformerFactory:主要用來取得Transformer類的實例
•Transformer:完成輸出
•DomSource:主要用來接收document對象
•StreamResult:指定要使用的輸出流對象
案例:
package cn.org.kingdom.dom; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; public class DomCreate { public static void main(String[] args) throws ParserConfigurationException, TransformerException, FileNotFoundException { TransformerFactory tff = TransformerFactory.newInstance(); Transformer tf = tff.newTransformer(); //構建一個新的xml文檔 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.newDocument(); //建立根元素節點 Element root = doc.createElement("heros"); doc.appendChild(root); //第一個子元素 Element hero1 = doc.createElement("hero"); hero1.setAttribute("id", "h01"); Element elGuan = doc.createElement("name"); elGuan.setTextContent("關羽"); Element elAge = doc.createElement("age"); elAge.setTextContent("13"); hero1.appendChild(elGuan); hero1.appendChild(elAge); root.appendChild(hero1); //第二個子元素 Element hero2 = doc.createElement("hero"); hero2.setAttribute("id", "h02"); Element elDiaoc = doc.createElement("name"); elDiaoc.setTextContent("貂蟬"); Element elAge2 = doc.createElement("age"); elAge2.setTextContent("13"); hero2.appendChild(elDiaoc); hero2.appendChild(elAge2); root.appendChild(hero2); //建立輸入源 DOMSource ds = new DOMSource(doc); //建立輸出源 StreamResult sr = new StreamResult(new FileOutputStream("src"+File.separator+"create.xml")); //輸出的操做 tf.transform(ds, sr); } }
SAX的全稱是Simple APIs for XML,即XML簡單應用程序接口。
與DOM不一樣,SAX提供的訪問模式是一種順序模式,這是一種快速讀寫XML數據的方式。當使用SAX分析器對XML文檔進行分析時,會觸發一系列事件,並激活相應的事件處理函數,應用程序經過這些事件處理函數實現對XML文檔的訪問,於是SAX接口也被稱做事件驅動接口。
侷限性:
1. SAX分析器在對XML文檔進行分析時,觸發了一系列的事件,因爲事件觸發自己是有時序性的,所以,SAX提供的是一種順序訪問機制,對於已經分析過的部分,不能再倒回去從新處理。即一旦通過了某個元素,咱們沒有辦法返回去再去訪問它。
2. SAX分析器只作了一些簡單的工做,大部分工做還要由應用程序本身去作。也就是說,SAX分析器在實現時,只是順序地檢查XML文檔中的字節流,判斷當前字節是XML語法中的哪一部分、是否符合XML語法,而後再觸發相應的事件,而事件處理函數自己則要由應用程序本身來實現。同DOM分析器相比,SAX分析器缺少靈活性。
優點:因爲SAX分析器實現簡單,對內存要求比較低,(SAX沒必要將整個XML文檔加載到內存當中,所以它佔據內存要比DOM小), 所以實現效率比較高。對於大型的XML文檔來講,一般會用SAX而不是DOM。而且對於那些只須要訪問XML文檔中的數據而不對文檔進行更改的應用程序來講,SAX分析器更爲合適。
一、建立一個處理器,讓這個處理器繼承DefaultHandler類,並重寫相關的方法
package cn.org.kingdom.sax; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class MyDefaultHanler extends DefaultHandler { public void startDocument() throws SAXException { System.out.println("<?xml version='1.0' encoding='utf-8' ?>"); } public void endDocument() throws SAXException { System.out.println("xml文檔讀取結束"); } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.print("<"+qName); if(attributes!=null) { for(int i = 0;i<attributes.getLength();i++) { String attName = attributes.getQName(i); String value = attributes.getValue(i); System.out.print(" "+attName+"='"+value+"'"); } } System.out.println(">"); } public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("</"+qName+">"); } public void characters(char[] ch, int start, int length) throws SAXException { System.out.println(new String(ch,start,length)); } }
二、建立解析器類
•SAXParserFactory:主要用來建立SAXParser對象
•SAXParser:Parse(File f,DefaultHandler sax)
package cn.org.kingdom.sax; import java.io.File; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.SAXException; public class SaxDemo { public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { //建立一個sax解析器的工廠對象 SAXParserFactory spf = SAXParserFactory.newInstance(); //SAXParser建立 SAXParser sp = spf.newSAXParser(); //解析 sp.parse(new File("src"+File.separator+"demo01.xml"), new MyDefaultHanler()); } }
語言獨立:DOM 並非用人們心目中的 Java 語言設計的。雖然這種方法保留了在不一樣語言中很是類似的 API,它也使那些習慣 Java 語言的程序員感到更麻煩。例如:Java 語言內建了一種 String 類,而 DOM 則規範定義了本身的Text類。
嚴格的層次結構:DOM API 直接沿襲了 XML 規範。在XML中,每件東西都是一個結點,所以您能在DOM中找到一個幾乎每件東西均可以擴展的基於Node 的接口和返回Node 的一系列方法。就多態性的觀點來說,它是優秀的,可是它在Java語言中的應用是困難並且不便的,其中從Node向葉類型做顯式向下類型轉換會致使代碼的冗長和難以理解。
接口驅動:公共DOM API僅由接口組成。w3c 對提供實現並不感興趣,它只對定義接口(比較有意義)感興趣。但它也意味着做爲 Java 程序員使用 API 在建立 XML對象時增長了負擔,由於 w3c 標準大量使用工廠化的類和相似的靈活的但不直接的模式。
JDOM是一個開源項目,它基於樹型結構,利用純JAVA的技術對XML文檔實現解析、生成、序列化以及多種操做。JDOM 直接爲JAVA編程服務。它利用更爲強有力的JAVA語言的諸多特性(方法重載、集合概念等),把SAX和DOM的功能有效地結合起來,以彌補DOM及SAX在實際應用當中的不足之處。
即:JDOM=DOM的修改性+SAX的大文件可讀性,在使用設計上儘量地隱藏原來使用XML過程當中的複雜性。利用JDOM處理XML文檔將是一件輕鬆、簡單的事。
JDOM 主要用來彌補DOM及SAX在實際應用當中的不足之處。這些不足之處主要在於SAX沒有文檔修改、隨機訪問以及輸出的功能,而對於DOM來講,JAVA程序員在使用時來用起來總以爲不太方便。
案例1:解析操做
package cn.org.kingdom.jdom; import java.io.File; import java.io.IOException; import java.util.List; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; public class JdomParser { public static void main(String[] args) throws JDOMException, IOException { SAXBuilder sbi = new SAXBuilder(); Document doc = sbi.build(new File("src"+File.separator+"demo01.xml")); Element rootEl = doc.getRootElement(); System.out.println("根節點爲:"+rootEl.getName()); System.out.println("根節點中的屬性有:"); List<Attribute> list = rootEl.getAttributes(); for(Attribute attr :list){ System.out.println(attr.getName()+"-->"+attr.getValue()); } System.out.println(rootEl.getChildText("sname")); System.out.println(rootEl.getChildText("addr")); List<Element> sublist = rootEl.getChildren(); for(Element e:sublist){ System.out.println(e.getName()+"-->"+e.getText()); } } }
package cn.org.kingdom.jdom; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.jdom.Comment; import org.jdom.Document; import org.jdom.Element; import org.jdom.output.XMLOutputter; public class JdomCreateDemo { public static void main(String[] args) throws FileNotFoundException, IOException { XMLOutputter out = new XMLOutputter(); Document doc = new Document(); //建立根節點 Element root = new Element("heros"); //設置根節點 doc.setRootElement(root); Element element1 = new Element("hero"); //採用一種代碼鏈的風格方式 element1.addContent(new Element("name").setText("曹操")) .addContent(new Element("age").setText("15")); Element element2 = new Element("hero"); element2.addContent(new Element("name").setText("百麗守約")) .addContent(new Element("age").setText("20")) .addContent(new Comment("這是一個註釋")); root.addContent(element1); root.addContent(element2); out.output(doc, new FileOutputStream("src"+File.separator+"jdom.xml")); } }
JDOM是做爲一種輕量級API 被制定的,最主要的是它是以Java爲中心的。它在遵循DOM主要規則的基礎上除去了上述缺點
JDOM 是 Java 平臺專用的,api使用 Java 語言的內建String支持,所以文本值也適用於 String 。它還可利用 Java 2 平臺的類集,如 List 和Iterator ,給程序員提供了一個豐富的而且和Java 語言相似的環境。
在 JDOM 中,XML 元素就是 Element 的實例,XML 屬性就是 Attribute 的實例,XML文檔自己就是 Document 的實例。因爲在XML 中全部這些都表明了不一樣的概念,所以它們老是做爲本身的類型被引用,而不是做爲一個含糊的「結點」。
類驅動,由於 JDOM 對象就是像 Document 、Element 和 Attribute 這些類的直接實例,所以建立一個新 JDOM 對象就如在 Java 語言中使用 new 操做符同樣容易。它還意味着不須要進行工廠化接口配置 -- JDOM 的使用是直截了當的。
當xml文檔的大小大於10m的時候,若是採用jdom會出現性能問題,此時咱們就能夠選擇dom4j
DOM4J是一套開源的類庫。與JDOM不一樣的是:DOM4J使用接口和抽象基類,它的API要複雜一些,可是靈活性更好 ,基於接口設計,在一些常見的框架中好比hibernate、mybati等都使用是dom4j
package cn.org.kingdom.dom4j; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.Iterator; import java.util.List; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class Dom4jParser { public static void main(String[] args) throws FileNotFoundException, DocumentException { SAXReader reader = new SAXReader(); Document doc = reader.read(new FileInputStream(new File("src"+File.separator+"demo01.xml"))); Element root = doc.getRootElement(); System.out.println(root.getName()); List<Attribute> list = root.attributes(); for (Attribute attr : list) { System.out.println(attr.getName()+"-->"+attr.getValue()); } //根據名稱直接獲取屬性的值 System.out.println(root.attributeValue("id")); System.out.println(root.attributeValue("age")); //獲取根元素下的子節點 System.out.println("====================="); List<Element> list2 = root.elements(); for (Element el : list2) { System.out.println(el.getName()+"-->"+el.getText()); } System.out.println("****************************"); Iterator<Element> iter = root.elementIterator(); while(iter.hasNext()) { Element e = iter.next() ; System.out.println(e.getName()+"-->"+e.getText()); } } }
package cn.org.kingdom.dom4j; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.XMLWriter; public class Dom4jCreateDemo { public static void main(String[] args) throws IOException { OutputStream is = new FileOutputStream(new File("src"+File.separator+"dom4j.xml")); XMLWriter writer = new XMLWriter(is); //注意:這裏建立document沒有jdom的中方便了 Document doc = DocumentHelper.createDocument(); Element root =DocumentHelper.createElement("stu"); doc.setRootElement(root); root.addAttribute("sid", "s01"); Element elName = DocumentHelper.createElement("name").addText("zhangsan"); Element elAge = DocumentHelper.createElement("age").addText("15"); root.add(elName); root.add(elAge); writer.write(doc); } }