2007-07-15 11:33
關于JAXP,DOM,SAX,JDOM,DOM4J的一些想法
這些API是XSLT的關鍵部分,它們構建在DOM和SAX解析器基礎上。
Sun在XML領域總是后知后覺,等到Sun重視XML的時候,XML的API早就滿天飛了,尤其是IBM具有非常大的領先優勢。不過Sun是規范
的制訂者,于是參考WOffice:smarttags"
/>3C的標準制訂了JAXP規范。JAXP不像Xerces和Crimon那樣,它只是一個spec,本身是不做任何事情的,它的作用就是提出一
個統一的接口,讓其它的XML API都來遵循JAXP編程,那么用JAXP寫出來的程序,底層的API可以任意切換。
具體來說JAXP包括了幾個工廠類,這就是JDK1.4里面的Javax.xml.parsers 包,用來尋找符合DOM標準的XML
API實現類的位置;此外JAXP還包括一整套interface,這就是JDK1.4里面的org.w3c.dom那幾個包。工廠類負責加載DOM的實
現類。
當你嚴格采用JAXP編程的時候,是遵循W3C的DOm標準的,那么在JAXP底層你實際上可以任意切換不同的DOM實現,例如Xerces,或者Crimon,再或者其它,切換方法就是配置jaxp.properties。因此JAXP就是一些標準接口而已。
JAXP應用程序 -> JAXP接口 -> Xerces DOM實現 -> Xerces DOM/SAX 解析器
JAXP應用程序 -> JAXP接口 -> Crimson DOM實現 -> Crimson DOM/SAX 解析器
JAXP應用程序 -> JAXP接口 -> Crimson DOM實現 -> Xerces DOM/SAX 解析器
W3C的DOM標準API難用的讓人想撞墻,于是有一幫人開發Java專用的XML
API目的是為了便于使用,這就是jdom的由來,開發到一半的時候,另一部分人又分了出來,他們有自己的想法,于是他們就去開發dom4j,形成了今天
這樣兩個API,至于他們之間的性能,功能之比較看看上面我推薦的文章就知道了,jdom全面慘敗。
jdom 相當于上面的 JAXP接口 + Xerces DOM實現部分,它本身沒有解析器,它可以使用Xerces或者Crimson的解析器即
JAXP應用程序 -> JAXP接口 -> Xerces DOM實現 -> Crimson DOM/SAX 解析器 或 Xerces DOM/SAX 解析器
jdom應用程序 -> jdom API -> Xerces/Crimson解析器
dom4j應用程序 -> dom4j API -> Xerces/Crimson解析器
dom4j應用程序 -> dom4j API -> Alfred2解析器
因此可以看出采用dom4j/jdom編寫的應用程序,已經不具備可移植性了。
Sun是JAXP標準的制訂者,甚至很執著的在JDK1.4里面綁定Crimson DOM實現和解析器,然后可笑的是,Sun自己的JAXM RI竟然不是用JAXP寫出來的,而是dom4j
我的舉例:
1. 僅僅是XSL轉換。XMLàHTML,通過XSL
Import javax.xml.transform.TransformerFactory;
Import javax.xml.transform.Transformer;
Import javax.xml.stream.StreamSource;
Import javax.xml.stream.StreamResult;
import java.io.FileOutputStream;
TransformerFactory transFactory = TransformerFactory.newInstance();
Transform transformer = transFacyory.newTransformer(new StreamSource(XMLSheetName));
Transformer.transform(new StreamSource(XMLFileName),new StreamResult(new FileOutputStream(outputURL)));
這里的stream是一個DOM對象。
我感覺這個就是JAXP應用程序 -> JAXP接口 -> Xerces DOM實現 -> Xerces DOM/SAX 解析器,不知道對不對。
2.遍歷XML,通過DOM。不僅僅是XSL轉換。中間有對XML元素內容的操作。
Import javax.xml.transform.TransformerFactory;
Import javax.xml.transform.Transformer;
Import javax.xml.stream.StreamSource;
Import javax.xml.stream.StreamResult;
import java.io.FileOutputStream;
//Xerces解析器來完成DOM遍歷XML.DOMParser是Xerces包的一部分。
Import org.apache.xerces.parsers.DOMParser;
Import org.w3c.dom.Document;
Import org.w3c.dom.NodeList;
//DOM遍歷XML
DOMParser parser = new DOMParser();
Parser.parse(XMLFileName);//解析并在內存中創建XML樹。
Document document = parser.getDocument();//通過Document對象,可以使用內存中的樹。
NodeList products = document.getElementByTagName(“product_id”);
Int num_products = products.getLength();
//XSL轉化器
TransformerFactory transFactory = TransformerFactory.newInstance();
Transform transformer = transFacyory.newTransformer(new StreamSource(XMLSheetName));
Transformer.transform(new StreamSource(XMLFileName),new StreamResult(new FileOutputStream(outputURL)));
我感覺XSL轉化和對XML對象的操作是兩個過程??梢苑謩e對待。最重要的是對對象的操作。這也就是為什么有DOM,JDOM,DOM4J。轉化好像只需要JAXP就可以了,關心的是StreamSource和StreamResult。這兩個是DOM對象。
3.JDOM使用,生成Document內容并保存到XML文件。
import org.jdom.Element;
import org.jdom.Document;//和Import org.w3c.dom.Document對比一下。一個是JAXP的一個是JDOM的Document
import org.jdom.output.XMLOutputter;
Element root = Element(“orders”);
root.addContent(“ ”);
org.jdom.Document document = new Document(root);//創建JDOM樹。
FileOutputStream outStream = new FileOutputStream(XMLFileName);
XMLOutputter outToFile = new XMLOutputter();
outToFile.output(document,outStream);
outStream.flush();
outStream.close();
jdom應用程序 -> jdom API -> Xerces/Crimson解析器
VS
JAXP應用程序 -> JAXP接口 -> Xerces DOM實現 -> Xerces DOM/SAX 解析器
這里的沒有Transform的過程,直接把Document的內容存到XML中。沒有XSL轉化,沒有XSL文件。
JDOM提供了幾種輸出方法。這里XMLOutputter是保存到文件,輸出一個實際的XML流。還有DOMOutputter,在內存中創建一個傳統的DOM樹。還有SAXOutputter,創建一串SAX事件以便被其他對象讀取。
4.JDOM使用,讀取已有的XML然后生成Document,修改Document
import org.jdom.Element;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;
import org.jdom.input.SAXBuilder;
SAXBuilder builder = new SAXBuilder();
Document document = builder.build(XMLFileName);
Element order = Element(“orders”);
orders.addAttribute(“order_id”,session_id);
Element root = document.getRootElement();//root是已經存在的根元素。
Root.addContent(order);//在根元素里增加orders元素。
//把document保存到文件中。
FileOutputStream outStream = new FileOutputStream(XMLFileName);
XMLOutputter outToFile = new XMLOutputter();
outToFile.output(document,outStream);
outStream.flush();
outStream.close();
即使創建一個DOM式的結構,這里仍使用SAXBuilder來做這這件事情。
DOMBuilder和SAXBuilder中的”DOM”和”SAX”指的是用于建立文檔的方法,而不是生成的內容。
5.XSL轉換,能把DOM對象轉化成輸出,也可以向上面所舉例的把XMLFileName的流轉化成輸出的流(文件或屏幕顯示)。但是不能把JDOM對象轉化,所以需要把JDOM轉化成DOM對象,然后再輸出。
import org.jdom.Element;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;
import org.jdom.input.SAXBuilder;
//XSL轉化需要的包
import org.jdom.output.DOMOutputter;//對比org.jdom.output.XMLOutputter;
Import javax.xml.transform.TransformerFactory;
Import javax.xml.transform.Transformer;
Import javax.xml.transform.DOMSource;//對比Import javax.xml.stream.StreamSource;
Import javax.xml.stream.StreamResult;
org.w3c.dom.Document DOMDoc;
DOMOutputter DomOut = DOMOutputter();
DOMDoc = DomOut.output(org.jdom.Document);//把jdom的document轉化成DOM的document
TransformFactory transFactory = TransformFactory.newInstance();
Transformer transformer = transFactory.newTransformer(new DOMSource(DOMDoc));//感覺錯了,應該是XSL文件。
Transformer.transform(new DOMSource(DOMDoc),new StreamResult(out));
//對比以前的轉化,是從文件到文件,現在是DOM樹到屏幕輸出。
TransformerFactory transFactory = TransformerFactory.newInstance();
Transform transformer = transFacyory.newTransformer(new StreamSource(XMLSheetName));
Transformer.transform(new StreamSource(XMLFileName),new StreamResult(new FileOutputStream(outputURL)));