<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-128  評論-55  文章-5  trackbacks-0

    處理 XML 的 API
    基于 XML 的應用程序從邏輯上分成 3 個層次,下面是 XML 文檔或數據,中間是 XML 解析器,上面是 XML 應用程序。XML 解析器的作用是讀入 XML 文檔或數據,將 XML 建造(build)為內存中的數據結構,便于應用程序處理,或者根據 XML 中包含的信息,調用應用程序提供的回調方法。由于 XML 是基于文本的,具有平臺中立性,各種語言都有相應的 XML 解析器。

    處理 XML 的 API 有這幾種:DOM、SAX、JAXP、JDOM 和 DOM4J,這幾種是最常用的,還有其它的一些不常用的 API。其中 DOM 可以用于多種語言,SAX 可以用于 Java 與 C++,JAXP、JDOM 和 DOM4J 只能用于 Java。一個 XML 解析器至少需要實現 DOM 或 SAX 兩種 API 中的一種,不過現在常用的 Java XML 解析器都同時實現了 DOM、SAX 和 JAXP 3 種 API。JDOM 和 DOM4J 是由單獨的包(jar)來實現的,使用 JDOM 和 DOM4J 需要得到標準的 XML 解析器的支持。目前在眾多的 Java XML 解析器中使用最廣的是 Xerces 和 Crimson,它們都是開源軟件組織 Apache 軟件基金會資助的開源軟件。其中 Xerces 最初的代碼來自 IBM 的貢獻,Crimson 最初的代碼來自 Sun 的貢獻。JDK 1.4 以后的版本中已經包括有 XML 解析器,因此不再需要另外的 XML 解析器。IBM JDK 1.4 本帶的 XML 解析器是 Xerces 的早期版本,Sun JDK 1.4 本身帶的 XML 解析器是 Crimson 的早期版本(孩子總是自家的親)。不過即使使用 JDK 1.4,你仍然可以使用其它的 XML 解析器。在我們的開發中全部使用 Xerces,主要是因為 Xerces 在所有 Java XML 解析器中功能是最豐富的,根據性能測試 Xerces 的性能要比 Crimson 好的多,而且我們在 Linux 上出于性能的考慮全部使用 IBM 的 JRE/JDK。


    [PS: XML4J簡史。XML4J 由 Hiroshi Maruyama 在“IBM 東京研究實驗室”開發,它可以分解并解釋 XML 文檔,以便機器和應用程序讀取。在 1998 年 W3C 宣布建議的 XML 規范的同一天,XML4J 作為免費試用下載軟件進入 alphaWorks 網站。從那時起,XML4J 的日漸流行導致人們對 alphaWorks 網站上的該技術要使用商業許可證選項,并將它作為一部分包括在 IBM 的 WebSphere Application Server 中。其它公司(包括 Vervet Logic、NC.Focus 和 First Union)也在其最新軟件中采用該技術。1999 年,IBM 通過將源碼捐贈給“Apache 軟件基金會”,將源碼發放給在此技術基礎上構建程序的社區。需要正式 XML4J 支持的開發人員可以通過 IBM 產品 WebSphere Application Server 或 Visual Age for Java 的產品來獲得支持。否則,只能通過 alphaWorks 的 XML4J 論壇獲得支持。XML4J 后演變為了Xerces。]

    參見:Xerces、XML4J 和 XML4C 添加了對 XML Schema 的支持 http://www.ibm.com/developerworks/cn/xml/x-parup/

    [PS: 在2002.6月的時候,apache有三個java解析器:Crimson,Xerces1,Xerces2。由于歷史原因,apache接收了兩個不同公司的捐贈。一個是IBM的xml4j,現在變成了現在的Xerces1.另外一個是SUN捐贈的Project x,變成了現在的Apache Crimson.
    而Xerces2是一個重寫的解析器。它的目標是可維護,模塊化,某些執行性能,這是前兩版本沒有達到的目標。xerces2的設計是為了滿足Apache項目的長期發展。]


    DOM 簡介:
    DOM 對于 XML 的處理方式就是把整個 XML 讀到內存中形成一棵樹狀結構,然后用各種方法對這棵數進行遍歷、插入、刪除、修剪等操作。因為 DOM 是 W3C 的正式標準,所有的語言都有支持 DOM 的解析器,包括 Java、C/C++、Perl、JavaScript 等等。DOM 的優點是信息量豐富(全部都在內存中),而且可以隨機訪問,尤其是在處理前后相互關聯的元素時非常方便。DOM 的缺點是 XML 應用程序在處理 XML 之前必須先由 XML 解析器把整個 XML 讀進內存并生成樹狀結構,如果 XML 非常大,例如 10M,解析的過程是非常慢的。如果再加上 XSLT 轉換(這是一種必須要使用 DOM 的操作)這類同樣耗費資源的操作,可能會耗盡系統的內存資源。所以標準 DOM 只適合于中小型 XML 的處理。

    SAX 簡介:
    為了更好地解決大型 XML 處理的問題,Java 開發人員發明了 SAX。SAX 采用事件驅動的方式來處理 XML,它的處理方式是:為每一個元素、屬性、內容(這些都認為是事件)定義一個回調方法,這個回調方法由應用程序提供。解析器以數據流的方式讀入 XML,當遇到某個元素、屬性、內容時就調用相應的回調方法。SAX 的優點是處理效率高,適合處理大型 XML。缺點是 SAX 對 XML 是只讀的,不能夠對 XML 進行寫操作,而且 SAX 處理 XML 中前后相互關聯的元素時也沒有 DOM 方便,因為應用程序必須自己保留以前事件的狀態信息。但是 SAX 還是取得了巨大的成功,后來 SAX 還被移植到了 C++ 等語言中。SAX 更詳細的優缺點可以查看《XML 高級編程》第 6 章的內容,我們這里有這本書的電子版。

    JAXP 簡介:
    你們對 XML 熟悉了以后可能會經常聽到 JAXP 這個詞。JAXP 其實不是一個獨立的 XML API,它的作用是為了解決不同的 XML 解析器之間的兼容性問題的。在 Sun 推出 JAXP 之前,商業公司(IBM、Oracle、Sun,etc.)、XML 專業研究者以及開源軟件愛好者開發出來多種多樣的 XML 解析器。這些解析器有的僅僅實現了 DOM API,有的同時實現了DOM 和 SAX。在我學習 XML 的過程中,我所知道的 Java XML 解析器就有 7、8 種。這些不同的 XML 解析器各有各的特長,它們雖然都遵從 W3C DOM 或 SAX 的規范,但是或多或少存在著一些差別,這使得為一種解析器編寫的應用程序移植到另一種解析器變得有些困難(也不是非常困難,只是不太方便)。為了解決這個問題,Sun 在 DOM、SAX 的 API 之上加了一個抽象層(基本上就是加了一個抽象工廠的設計模式,如果你們對設計模式有所了解的話),這就是 JAXP。JAXP 主要采用反射的方式來工作,可以動態加載所使用的 XML 解析器。使用 JAXP 來做 XML 開發,可以完全忽略不同的 XML 解析器之間的差別,不需要修改代碼就可以更換成另外的 XML 解析器。JAXP 目前已經得到大多數 Java XML 解析器的支持。除了封裝 DOM、SAX 的那些工廠類外,JAXP 還包含用于 XSLT 轉換的 API(也是一些工廠類),這些功能在 javax.xml.transform 這個包里。

    JDOM 簡介:
    除了 SAX,Java 開發人員還發明了 JDOM。雖然名字里有 DOM,JDOM 其實與 DOM 毫無關系。JDOM 嚴格說來其實是一種對象模型,除了處理 XML,還可以用于很多其它用途。JDOM 的輸入可以有多種格式,輸出也可以有多種格式。這些格式包括 XML 文件或數據流、Java 屬性文件、標準 DOM 樹等等。JDOM 利用 SAX 或 DOM(一般是用 SAX,極少用 DOM)讀入 XML 中的信息后在內存中生成自己的數據結構,就是通過組合(composition)關系嵌套在一起的一系列對象,然后用 Java 程序員最習慣的面向對象的方式來處理這些數據,處理結束后可以非常方便地輸出成各種格式。和 DOM、SAX 相比,用 JDOM 來做 XML 開發更加容易(代碼量更少)。JDOM 的主要的缺點是最初的設計未考慮性能問題,因此性能很差,而且全部使用具體類來實現導致了靈活性較差,但是考慮到易用性和開發效率,JDOM 仍然得到了廣泛的使用。

    DOM4J 簡介
    由于 JDOM 本身存在著一些設計缺陷,開發到一半,JDOM 的一些開發人員分了出來重新啟動了一個開源項目 DOM4J。DOM4J 與 JDOM 所要達到的目標是一樣的,即提供一套比 DOM、SAX 使用更加方便的處理 XML 的 API,同時避免 DOM、SAX 的主要缺點。DOM4J 重新做了設計,完全基于接口和多態,因此提高了靈活性。DOM4J 在概念上對 XML 的理解與 DOM 非常相似,只要你理解了 DOM,你就可以輕而易舉地理解 DOM4J,實際上 DOM4J 可以看做是一個更好的 DOM 實現。而且 DOM4J 保持了 JDOM 的易用性,性能上也比 JDOM 有了非常大的提高。最值得一提的是 DOM4J 完全支持 XPath,看看 DOM4J 的這段代碼:

    代碼:
    List list = document.selectNodes( //foo/bar );
    Node node = document.selectSingleNode(//foo/bar/author);

    這與我們前臺寫的 JavaScript 是非常相似的,我們學會 DOM4J 是幾乎不需要花什么時間。
    DOM4J 與 JDOM 一樣,通過 SAX 或 DOM(一般用 SAX)讀入 XML 中的信息在內存中生成自己的數據結構,因此 DOM4J 至少需要一個實現了 SAX 的 XML 解析器,我們可以直接使用 Xerces。
    由于 DOM4J 具有易用性、性能、靈活性、功能強大等多方面的優勢,今后我們如果需要在服務器端做 XML 開發,DOM4J 將是我們主要采用的工具。

    關于這幾種 API 的詳細內容,請參考《Java 與 XML》和《XML 高級編程》。關于 DOM4J,主要有這些資料:
    http://dom4j.sourceforge.net/faq.html
    http://www.csdn.net/develop/article/22/22753.shtm

    聽了我上面的介紹你們可能會覺得 DOM 是比 SAX 更基礎的 API,因為它是 W3C 的標準,所有的語言都支持,而 SAX 的使用僅局限于少數幾種語言。某種程度上你是對的,但是在 Java 的世界里,SAX 是比 DOM 更加基礎的 API。由于 SAX 處理效率很高,SAX 的應用范圍比 DOM 更廣。例如:我們中間件的低層框架 Avalon(也是 Apache 軟件基金會的產品)處理 XML 配置文件時使用的就是 SAX。另外,因為 W3C 并沒有規定在內存中如何生成一棵 DOM 樹(W3C 只規定了如何操作這棵 DOM 樹),Xerces 采用高效率的 SAX 來讀入 XML,然后生成 DOM 樹。因此當你在用 Xerces 做 DOM 開發時發現經常需要捕獲 SAXException 就沒什么可奇怪的了。JDOM 和 DOM4J 通常也是使用 SAX 讀入 XML,然后生成自己的數據結構。對于 JAXP、JDOM 和 DOM4J 來說,DOM 和 SAX 都是基礎的 API。

    在我們公司做開發最常接觸的 XML 開發是使用 JavaScript 做 DOM 開發,因為時間有限,所以我今天只詳細講一下在前臺使用 JavaScript 和 DOM API 做 XML 開發的過程。今天的目的主要是讓大家對于 XML 相關的知識有一個整體的了解。

    大家知道 JavaScript 是嵌入在瀏覽器中的,創建 DOM 樹不是 JavaScript 的責任,瀏覽器已經創建好了,另外通常 JavaScript 也不能直接讀寫 XML 文件(在權限許可的情況下 JavaScript 可以讀寫本地文件)。JavaScript 處理的 XML 數據有兩個來源,一個是來自于頁面中的 XML 數據島,另外一個是來自于從 XMLHTTP 接口接收的后臺發來的 XML 數據。注意:在瀏覽器中的 DOM 有兩種,HTML DOM 和 XML DOM。如何處理 HTML DOM 在普通的 JavaScript 教材(《JavaScript 權威指南》等等)中已經講得很詳細了,我這里只詳細講一下如何處理 XML DOM,下面所說的 DOM 都是指 XML DOM。在講 XML DOM 之前我首先要講一下 XPath。

    什么是 XPath?簡單地說,XPath 就是定位 XML 中某些節點(元素、屬性、內容、處理指令、文檔類型定義、注釋)的方法。XPath 的目的是為 XSLT 和 XPointer 提供一個共同的、整合的語法,用來對應 XML 的各個部分,選擇 XML 中的某個或某些節點。XPath 是在 DOM 樹中查找節點、做 XSLT 轉換、定義文檔內部指針(XPointer)的基礎。有時候也把一個符合 XPath 規范的表達式稱做一個 xpath。我們通常把 XPath 表達式的結果稱為一個節點集(node set)。節點集能夠被轉換、復制、忽略或執行其它的合法操作。XPath 除了包括定位語法外還包括很多函數定義,這些函數分成 4 類:節點集函數、字符串函數、布爾函數和數值函數。節點集函數,例如 position() 和 count(),通常以節點集作為輸入(以 XPath 表達式的形式),然后做進一步處理。其它 3 種類型的函數,例如 substring()、not() 和 round() 提供基本的字符串處理、邏輯運算和數值運算的功能。關于 XPath 中各種函數定義的詳細內容可以參考《XML 高級編程》這本書。所有這些表達式語法或函數定義都是 XPath 規范或實現的一部分。

    好了,長話短說,我在這里主要講一下 XPath 如何使用。其實我們需要知道的基本上就是《無廢話 XML》中表 7.1 的內容。
    XPath 的定位語法與操作系統目錄結構的語法非常相似。也分成兩種,相對路徑與絕對路徑。相對路徑從當前正在處理的節點開始,絕對路徑從文檔的根節點開始。我來舉些例子:
    代碼:
    A               對應當前節點下所有名為 A 的子元素。
    *               對應當前節點下所有子元素。
    */A               對應自當前節點開始,所有名為 A 的孫元素。
    @A               對應一個附屬于當前節點,名為 A 的屬性。
    @*               對應所有附屬于當前節點的屬性。
    text()            對應當前節點的子元素中的所有文本節點。
    .               對應當前節點
    ..               對應當前節點的父節點。
    A[1]            對應當前節點下,第一個名為 A 的子元素。
    A[position()=1]      作用同上。
    A/[@B="true"]      對應當前節點下所有名為 A 的子元素,這個子元素必須含有一個名為 B 的屬性,其屬性值必須為 "true"。
    A|B               對應當前節點下,所有名為 A 或 B 的子元素;| 代表“或”的關系。
    .//A            對應當前節點下,所有名為 A 的元素;// 符號代表可跨越數級。
    A//B            對應到所有名為 B 的元素,它們的上級(可跨越數級)必須有一個名為 A 的元素,而且 A 元素必須是當前節點的子元素。
    /A               對應根節點下所有名為 A 的子元素。
    //A               對應根節點下所有名為 A 的元素。A 元素可以在任意層次。


    我們在做前臺開發時,有兩個方法會用到 XPath,selectSingleNode() 和 selectNodes()。這兩個方法是 IE 的擴展,不屬于 W3C DOM 規范,但是使用起來非常方便,所以我們在 DOM4J 中也可以看到這兩個方法。
    代碼:
    hwn.__drTags = sr1.selectSingleNode("./tag");
    var cxn = xn.selectNodes("./*[not(@m:f) or @m:f!='d']");


    上面是從我們的前臺開發框架中 copy 出來的代碼。
    selectSingleNode 用于獲得一個節點,如果有多個節點滿足條件,返回的是第一個節點。
    selectNodes 用于獲得節點集,返回的結果是包含所有滿足條件節點的數組。

    第二條語句的參數看起來有些復雜,它的意思是找到 xn 節點下所有不包含 m:f 屬性或者包含 m:f 屬性,但屬性值不等于 'd' 的所有子元素。


    下面我來詳細講解 XML DOM 在 JavaScript 中的實現。
    在瀏覽器中,無論 XML 的數據來源如何,最后都會由瀏覽器生成一棵 DOM 樹。這棵 DOM 樹所對應的對象類型為 XMLDocument,這棵 DOM 樹上的所有節點(包括根節點)都是 XMLNodes 類型的對象。事實上 XMLDocument 也是 XMLNodes 的子類,所以你可以在任何一種 XMLNodes 派生出的對象上調用 selectSingleNode 和 selectNodes。

    數據來自 XML 數據島:
    例如在頁面中有這樣一個 XML 數據島,
    <xml id="book">
    ...
    </xml>

    var xd = book.XMLDocument;

    通過外部 XML 文件創建新的 DOM 樹:
    var xd = new ActiveXObject("Microsoft.XMLDOM");
    xd.load(data.xml);

    或者將外部文件中的數據加載到 XML 數據島:
    var xd = book.XMLDocument;
    xd.load(data.xml);

    注意:load() 這個方法的參數可以是任意合法的 URL,不一定限制為文件名。

    將數據保存到 XML 文件用
    xd.save(data.xml);

    通過字符串創建新的 DOM 樹:
    var xd = new ActiveXObject("Microsoft.XMLDOM");
    xd.loadXML("<"+hd.__hwnodes.style.rootTag+"></"+hd.__hwnodes.style.rootTag+">");


    數據來自 XMLHTTP:
    var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    xmlhttp.open("GET","/hwsvr2/qe",false);
    xmlhttp.send(null);
    var xd = xmlhttp.responseXML;

    得到 XML 文檔的根節點:
    var xn = xd.documentElement;


    我再來說說在 Mozilla 中創建 XML DOM 樹的方法,將來我們有可能會為 Mozilla 開發頁面,所以對于如何保持腳本的兼容性有些了解是有好處的,這部分內容不是必須掌握的內容。
    Mozilla 中并沒有 IE 的 XML 數據島這個概念,不過在 Mozilla 中模擬 XML 數據島是非常容易的,這里有這方面的資料:
    http://www.mozilla.org/xmlextras/xmldataislands/
    感興趣的可以看看。

    Mozilla 中內建有對 XML DOM 的支持,并沒有使用 ActiveX 之類外掛的方式(被 Mozilla 開發者譏笑為打補丁的方式)。在 Mozilla 中訪問創建好的 DOM 樹的方法與 IE 中基本上是一樣的,所不同的是創建 DOM 的過程,Mozilla 采用的方法都是符合 W3C 標準的方法:

    通過外部 XML 文件創建新的 DOM 樹:
    var xd= document.implementation.createDocument("","",null);
    xd.load("data.xml");

    第一個參數是名字空間的 URL,第二個參數是 DOM 根元素名稱,第三個參數是定義 XML 格式的 DTD。在這里這 3 個參數都可以不提供。

    Mozilla 中沒有 loadXML() 這個簡單的方法,但是可以手工為 Mozilla 添加這個方法,詳細信息在這里:
    http://webfx.eae.net/dhtml/xmlextras/xmlextras.html

    數據來自 XMLHTTP:
    var xmlhttp=new XMLHttpRequest();
    xmlhttp.open("GET","/hwsvr2/qe",false);
    xmlhttp.send(null);
    var xd = xmlhttp.responseXML;


    得到 XML 文檔的根節點:
    var xn = xd.documentElement;

    由上面可以看到只要創建了 XML DOM 樹后,訪問方法 IE、Mozilla 是完全一樣的,這部分的差異非常容易通過封裝的方法屏蔽掉。Mozilla 沒有提供 selectSingleNode() 和 selectNodes() 兩個方法,以前我寫過這兩個方法在 Mozilla 上的實現,貼在論壇上,感興趣的可以看看:
    http://forum.hibernate.org.cn/viewtopic.php?t=965


    下面我來講講訪問 DOM 樹常用的方法。

    剛才我們說到過,DOM 樹的訪問有兩個級別,文檔級別和節點級別。

    在文檔級別,XMLDocument 對象上有這些方法:
    abort():終止正在進行的異步下載
    getElementByTagName():根據標記名稱查找當前節點的子元素。
    load():從指定位置下載 XML。
    save():將 XML 保存到指定位置。

    XMLDocument 對象上有這些屬性:
    async:指出 XML 是否可以異步下載。
    doctype:返回 XML 的 DTD 節點。
    documentElement:返回 XML 的根元素。
    parseError:返回包含 parse error 信息的對象。

    在節點級別,XMLNodes 對象上有這些方法:
    createElement():在當前節點下創建一個子元素。
    createTextNode():在當前節點下創建一個內容節點。

    appendChild():在當前節點上添加新的子節點。
    cloneNode():復制一個節點,返回值為生成的新節點。
    hasChildNodes():當前節點是否為葉節點。
    insertBefore():在某節點前插入新的節點。
    removeChild():刪除當前節點的子節點。
    replaceChild():替換當前節點的子節點。

    XMLNodes 對象上有這些屬性:
    childNodes:包含所有的子節點數組。
    firstChild:當前節點的第一個子節點
    lastChild:當前節點的最后一個子節點
    nextSibling:當前節點的下一個兄弟節點
    nodeValue:節點值
    ownerDocument:當前節點對應的 XML 文檔
    parentNode:當前節點的父節點。
    parentElement:父元素的句柄。
    xml:從當前節點開始子樹所生成的 XML。這個屬性只有 IE 支持。

    對于所有的元素節點,可以使用這兩個方法:
    setAttribute():設置當前元素的屬性。
    getAttribute():獲得當前元素的屬性。
    clearAttributes():清除當前元素的所有屬性。

    另外還有 selectSingleNode() 和 selectNodes(),這兩個方法其實是最常用的了。由于 XML DOM 中可以使用強大的 XPath 查找你想要查找的任意節點,比 HTML DOM 中僅能用 all()、getElementById()、getElementByTagName() 幾個功能有限的方法方便得多。
    只要你理解了 DOM 的概念,并且沒有忘記以前學的數據結構的知識,上面的這些方法理解起來是非常簡單的,我就不細講了,關鍵是要經常使用,熟能生巧。



    Author: orangelizq
    email: orangelizq@163.com

    歡迎大家訪問我的個人網站 萌萌的IT人
    posted on 2007-07-14 14:27 桔子汁 閱讀(1375) 評論(0)  編輯  收藏 所屬分類: Web Service
    主站蜘蛛池模板: 永久免费毛片手机版在线看| 亚洲a一级免费视频| 亚洲午夜无码久久久久软件| 亚洲av成人一区二区三区观看在线 | 香港a毛片免费观看| 亚洲AV无码久久寂寞少妇| jlzzjlzz亚洲jzjzjz| 亚洲日韩中文字幕| 皇色在线免费视频| www.黄色免费网站| 亚洲VA综合VA国产产VA中| 亚洲黄色高清视频| 人体大胆做受免费视频| 4虎永免费最新永久免费地址| 亚洲区日韩区无码区| 亚洲码和欧洲码一码二码三码| 污视频在线观看免费| 久久久无码精品亚洲日韩按摩 | 亚洲日韩乱码中文无码蜜桃臀网站 | 13小箩利洗澡无码视频网站免费| 永久免费观看的毛片的网站| 高潮毛片无遮挡高清免费 | 四虎一区二区成人免费影院网址| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 日本亚洲欧洲免费天堂午夜看片女人员| 亚洲老熟女五十路老熟女bbw| 免费a级毛片视频| 亚洲欧美日韩综合俺去了| 免费国产高清视频| 免费观看久久精彩视频| 国产亚洲色婷婷久久99精品| 特级毛片aaaa级毛片免费| 亚洲国产精品无码专区影院 | 亚洲成AV人片久久| 四虎影视在线永久免费观看| 亚洲三级在线观看| 性短视频在线观看免费不卡流畅| 精品日韩亚洲AV无码| 又黄又爽一线毛片免费观看| 日韩成人免费视频| 亚洲av无码成h人动漫无遮挡|