隨筆 - 3, 文章 - 152, 評論 - 17, 引用 - 0
          數據加載中……

          JAXP: Coding for Parser & Transformer Independence

          Author: Henry Chen                     譯者:李力
          介紹
          由于可擴展標記語言(XML)的易用性和輕攜性,其近年來獲得了極大的流行。它與Java結合起來,非常適用于可移植的數據和代碼。每一個與XML文檔打交道的Java程序員,無論是讀數據,還是進行數據轉換,都必須對Java API’s for XML Processing (JAXP)有一個很深的理解。編寫XML解析器無關的代碼有許多好處,JAXP API 是用于XML的,就像JDBC API是用于關系型數據庫的。這篇介紹性的文章幫助開發(fā)者學習JAXP API,并讓開發(fā)者對可插入層(pluggability layer)有一個很深的理解,這樣,開發(fā)者就可以在他們的應用程序中自如的更換解析器。
          JAXPack
             SUN推出了一個用于XML的Java API 和架構,稱其為Java XML Pack (JAXPack - http://java.sun.com/xml/javaxmlpack.html)。下載包中包括了現在行業(yè)中一些重要的標準。這篇文章中,我們將注意力放在JAXP(the API for XML Processing)上,Sybase的Easerver從版本3.6.1開始支持JAXP。
             首先,我們看一下JAXP提供的解析能力,解析XML文檔有兩種最基本的方法, 基于事件的SAX和遍歷樹的DOM。開發(fā)者可以選擇最適合他們需要的方法。讓我們鉆進去,深入的看一下這些API。
          這篇文章中,我們用圖1中的XML文檔來闡述我們的例子。


           
          SAX
          Simple API for XML Parsing (SAX)是事件驅動的,它從頭到尾遍歷整個文檔, 當它遇到一個語法結構時,它會通知運行它的程序,這些是通過事件處理接口ContentHandler, ErrorHandler, DTDHandler, 和 EntityResolver中的回調方法實現的。這些回調方法可以被開發(fā)者自定義實現來滿足一些特殊的要求。圖2描繪了SAX解析器解析文檔是各種組件之間的關系。
           

          我們將遍歷圖1中XML文檔,并且給出SAX解析器一行一行的解析是調用回調方法的細節(jié),在這個例子中,我們不包括對ignorableWhiteSpace方法調用。


          現在你已經對SAX如何工作有一個總體的了解,接下來,讓我們看一看用真真的Java代碼實現的例子,我們實現的程序的完整代碼可以在http://www.sybase.com/developer.上找到,出于這篇文章的目的,我將只用一些代碼相關部分的片斷。

          1. public class SAXExample extends DefaultHandler {
          2. SAXParserFactory factory = SAXParserFactory.newInstance();
          3. SAXParser saxParser = factory.newSAXParser();
          4. DefaultHandler handler = new SAXExample();
          5. saxParser.parse( new File(argv[0]), handler)

           
            注意我們繼承了DefaultHandler Class, 這個類用一些空方法實現了ContentHandler, ErrorHandle, DTDHandler,和 EntityResolver接口,這樣,程序員就可以只覆蓋一些他們需要的方法。
          在我們解析之前,我們首先需要通過調用newInstance方法,實例化一個SAXParserFactory,這個方法用某個特定的查找順序來決定使用哪一個SAXParserFactory的實現,這就意味著,解析器更改時,代碼無需重新編譯。
          一旦我們實例化了一個SAXParserFactory,我們可以設置三個選項,這些決定了隨后如何產生SAXParser的對象。
          SAXParserFactory  使namespace可用
          SetValidating     打開驗證
          SetFeature         設定底層實現的特征
          SAXParserFactory配置好后,我們調用newSAXParser方法來實例化一個JAXP SAXParser對象,這個對象包裝了一個底層的SAX解析器,并且允許我們以廠商中立的方式與其交互,現在,我們就可以解析了。在這個例子中,我們用File對象作為輸入,它還可以接受其他的輸入源,如InputSource對象,InputStream 對象,或者Uniform Resource Identifier (URI)。
          注意程序是如何使自己成為解析器的處理者(handler)的,這意味著解析器將調用SAXExampl中的回調方法的,當解析方法一行一行的解析XML文件時,我們的處理類中的回調事件就發(fā)生了。

          DOM
          Document Object Model (DOM)是將XML文檔解析成樹狀對象的一套接口,每一個對象,或結點(node)都有一個用org.w3c.dom包中的接口表示的類型(type).如Element, Attribute,
          Comment, 和Text。可以像操作其他任何樹狀數據結構一樣來操作DOM樹狀對象,它允許隨機訪問XML文檔中特定部分的數據,并且修改它,這些是SAX解析器做不到的。
               這種方法的缺點是它非常占用內存和CPU資源,因為構建DOM樹時需要將整個XML文檔讀入并保持在內存中。
           

          讓我們看一個例子:
          1.     public class DOMExample {
          2. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
          3. DocumentBuilder domParser = factory.newDocumentBuilder();
          4. Document document = domParser.parse( new File(argv[0]) );

          .
          與SAX類似,我們首先用newInstance方法實例化一個DocumentBuilderFactory對象,同樣類似SAXParserFactory,工廠可以配置用來處理namespace(命名空間)和validation(驗證)。另外,還有一些其他可選的設置,但這已經超出了本文的范圍。工廠對象準備好后,我們就可以創(chuàng)造一個DocumentBuilder對象,它可用來解析xml文件和創(chuàng)造Document對象,同樣類似SAXParser的parse方法,Document對象可以接受InputSource對象,InputStream對象,或者URI。

          1. Node thePhonebook = document.getDocumentElement();
          2. NodeList personList = thePhonebook.getChildNodes();
          3. Node currPerson = personList.item(0);
          4. Node fullName = currPerson.getChildNodes().item(0);
          5. Node firstName = fullName.getChildNodes().item(0);
          6. Node lastName = fullName.getChildNodes().item(1);
          7. Text firstNameText = (Text)firstName.getFirstChild();
          8. Text lastNameText = (Text)lastName.getFirstChild();
          9. Node phone = currPerson.getChildNodes().item(1);
          10. Node workPhone = phone.getChildNodes().item(0);
          11. Node homePhone = phone.getChildNodes().item(1);
          12. Text workPhoneText = (Text)workPhone.getFirstChild();
          13. Text homePhoneText = (Text)homePhone.getFirstChild();

          一旦我們擁有了Document DOM對象,我們就可以像操作其他樹一樣操作它。getDocumentElement方法返回根元素,從根元素可以得到子節(jié)點的NodeList,并且可以處理它們。在DOM樹結構的葉結點,我們可以找到Text對象,它繼承了Node。調用getData方法可以返回字符串的值。如你所見,使用者在操作數據時必須對文檔數據的結構有一個了解,而在SAX中,解析器僅僅對它遇到的數據反應。
          但是,DOM最大的優(yōu)點是它可以對數據結構進行修改,例如:

          1. if (firstNameText.getData().equals("Richard") &&
          2. lastNameText.getData().equals("Mullins")) {
          3.     homePhoneText.setNodeValue("(510)333-3333");
          4. }

          用setNodeValue方法可以改變DOM樹中的數據,隨后,我們將看XSLT如何將一個新樹寫入一個數據文件。
          XSLT
          XSL轉換(XSLT)是將XML文檔轉換為其他XML文檔或其他格式的文檔(如HTML)的一組API,  XML樣式語言(XSL)在轉換中作用巨大,用其定義的樣式表包含了格式規(guī)則,指定了文檔如何顯示。

           
          這里有一個例子,將DOM對象轉換為XML文檔:
          1. //create a new DOMSource using the root node of an existing DOM tree
          2. DOMSource source = new DOMSource(thePhonebook);
          3. StreamResult result = new StreamResult(System.out);
          4. TransformerFactory tFactory = TransformerFactory.newInstance();
          5. Transformer transformer = tFactory.newTransformer();
          6. transformer.transform(source, result);

          我們首先用newInstance方法實例化一個TransformerFactory對象,它用特定的查找順序來決定使用哪一個轉換器實現。和SAX和DOM工廠一樣,可以對TransformerFactory對象進行一些配置,來影響Transformer對象的創(chuàng)建。用newTransformer方法創(chuàng)建好Transformer對象后,就可以調用transform方法,它將一個Source對象(DOMSource,SAXSource, StreamSource)轉換為Result對象(DOMResult, SAXResult, StreamResult)。
          抽象層
          前面已經提到過,用某種特定的查找順序來決定使用哪個SAX, DOM 和XSLT的實現,下面的API定義了查找順序:
           .使用javax.xml.parsers.SAXParserFactory(或javax.xml.parsers.DocumentBuilderFactory)系統(tǒng)屬性(system property)。
           .使用JRE目錄中“l(fā)ib/jaxp.properties”屬性文件定義的javax.xml.parsers.SAXParserFactory屬性的值,這個值必須包括了實現類的全名。
           .使用Service API,它可以在運行系統(tǒng)中使用的JAR文件中包括的META-INF/services/javax.xml.parsers.SAXParserFactory文件中查找類名。
           .使用平臺默認的SAXParserFactory實例。
          使用DOM時,你只需將javax.xml.parsers.SAXParserFactory替換為javax.xml.parsers.DocumentBuilderFactory,類似,使用XSLT時,你用javax.xml.transform.TransformerFactory替換。
          總結
          如你所見,你寫的代碼只需與抽象層打交道。這保證了廠商的無關性,你可以快速和輕松的替換你的解析器的實現。解析XML文檔時,Java開發(fā)者可以根據他們的需要設置兩個選項。SAX是利用回調過程的事件驅動模型,而DOM是一種游歷樹的模型,它在操作數據前必須將XML文檔解析成樹,XSLT則可以將XML文檔轉換為另一種XML文檔或者其他格式,如HTML。總之,JAXP非常的強大,靈活,它提供的簡單可用的工具可以滿足大多數Java開發(fā)者處理XML文檔時的需要。

          posted on 2005-03-23 16:09 閱讀(212) 評論(0)  編輯  收藏 所屬分類: Java_Xml

          主站蜘蛛池模板: 延吉市| 徐水县| 安平县| 仁化县| 连州市| 子洲县| 南康市| 肥城市| 镇沅| 白水县| 社会| 南开区| 长子县| 阿拉尔市| 五台县| 特克斯县| 榆社县| 那曲县| 惠东县| 金坛市| 新源县| 大埔县| 金溪县| 获嘉县| 上饶市| 家居| 来凤县| 麦盖提县| 桃园县| 花垣县| 芮城县| 邹平县| 石河子市| 铅山县| 昌邑市| 莱阳市| 建瓯市| 随州市| 开封县| 南阳市| 闸北区|