日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

转 用 AXIOM 促进 XML 处理

發布時間:2024/1/18 asp.net 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转 用 AXIOM 促进 XML 处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://www.ibm.com/developerworks/cn/xml/x-axiom/

AXIOM 還不是另一種對象模型。它有著明確的設計目標:大幅提升 Apache 下一代 SOAP 協議棧 Axis 2 的性能。結果造就了不同于其他對象模型的 AXIOM(也稱為 OM),因為它突出了構造的輕型,并且 僅當需要的時候才建立。由于是輕型的,它盡可能地減輕對系統資源的壓力,特別是 CPU 和內存。同時,延遲構造又允許在其他部分還沒有完成的時候使用樹的一部分。AXIOM 強大的延遲構建能力源于底層的 Streaming API for XML (StAX) 解析器。AXIOM 提供了所有這些特性,同時幕后的復雜性對用戶是透明的。

使用 XMLBench Document Model Benchmark 測試(請參閱 參考資料)的結果表明,AXIOM 的性能和現有的高性能對象模型相當。但是 AXIOM 的內存占用要好于現有多數依靠 SAX 和/或 DOM 輸入輸出的對象模型。因此對于 Web 服務引擎或內存受限制設備這樣的 XML 處理器,AXIOM 是一種理想的選擇,它可用于一般的 XML 處理,但是有一個對 SOAP 優化了的可選層。

使用 AXIOM

在典型的 SOAP 引擎中,數據可能以三種不同的方法表示:

  • 序列化形式,如 XML 或二進制 XML。
  • 內存中基于樹的對象模型,如 DOM。
  • 專用于特定語言的對象,如 Plain Old Java Object (POJO)。

比如一個 Web 服務的調用。傳遞給服務提供商的數據可能是用語言專用的對象,對于 Java 技術就是 POJO。調用過程的第一步是將這些對象中的信息項放入 SOAP 信封,構造一個 SOAP 消息。因為 SOAP 消息是 XML 文檔,所以 Web 服務還必須將數據項轉化成要求的 XML 格式。在內存中表示 XML Infoset 需要構造一個對象樹,供對象模型(AXIOM)使用。

從頭創建 AXIOM

創建內存對象層次結構的第一步是創建一個對象工廠:

OMFactory factory= OMAbstractFactory.getOMFactory();

?

AXIOM 允許很多不同的對象工廠實現,但鏈表是最常用的。一旦建立了工廠,就可以開始構造樹了。

比如下面的 XML 片段:


清單 1.Line item 細節

?

<po:line-item po:quantity="2"

?? xmlns:po="http://openuri.org/easypo">

????? <po:description>

???????? Burnham's Celestial Handbook, Vol 2

????? </po:description>

???????? <po:price>19.89</po:price>

</po:line-item>

?

注意,所有的元素和屬性都屬于 "http://openuri.org/easypo" 名稱空間。因此,為這個 XML 片段構造 AXIOM 樹的第一步就是創建名稱空間,如下所示:

OMNamespace poNs= factory.createOMNamespace("http://openuri.org/easypo", "po");

?

現在可以構造包裝器元素 line-item 了:

OMElement lineItem= factory.createOMElement("line-item", poNs);

?

接下來創建 line-item 元素相關的子元素和屬性。

最好用下面的方式創建元素屬性:

lineItem.addAttribute("quantity", "2", poNs);

?

與其他元素一樣創建子元素,然后按照下面的方式結合到父元素中:

?? OMElement description= factory.

????? createOMElement("description", poNs);

???????? description.setText("Burnham's Celestial Handbook, Vol 2");

???????? lineItem.addChild(description);

?

類似地,也添加 price 子元素:

?? OMElement price= factory.createOMElement("price", poNs);

???????? price.setText("19.89");

???????? lineItem.addChild(price);

?

清單 2 顯示了完整的代碼片段。


清單 2.通過程序創建 line item

?

?? OMFactory factory = OMAbstractFactory.getOMFactory();

???????? OMNamespace poNs =

???????? factory.createOMNamespace("http://openuri.org/easypo", "po");

???????? OMElement lineItem =

???????? factory.createOMElement("line-item", poNs);

???????? lineItem.addAttribute("quantity", "2", poNs);

???????? OMElement description =

???????? factory.createOMElement("description", poNs);

???????? description.setText("Burnham's Celestial Handbook, Vol 2");

???????? lineItem.addChild(description);

???????? OMElement price = factory.createOMElement("price", poNs);

???????? price.setText("19.89");

???????? lineItem.addChild(price);

?

輸出

現在可以使用 StAX writer 來序列化構造好的元素:


清單 3.序列化 line item

?

?? XMLOutputFactory xof = XMLOutputFactory.newInstance();

?? XMLStreamWriter writer = xof.

? ????createXMLStreamWriter(System.out);

????? lineItem.serialize(writer);

????? writer.flush();

?

從已有代碼構造 AXIOM

現在看看相反的過程,從數據流建立內存對象模型。

最簡單的情況下,只需要關心 XML 片段的反序列化。但是在 SOAP 處理中,需要反序列化 SOAP 消息或者經過 MTOM 優化的 MIME 信封。因為與 SOAP 處理關系特別密切,所以 AXIOM 為此提供內置支持,稍候將詳細介紹。但首先要說明如何反序列化簡單的 XML 片段,具體來說就是剛剛序列化的那個 XML 片段。

首先構造一個解析器。AXIOM 支持用 SAX 和 StAX 解析器解析 XML。但是,SAX 解析不允許對象模型的延遲構造,因此在延遲構建很重要時,應該使用基于 StAX 的解析器。

第一步是為數據流獲得一個 XMLStreamReader:

File file= new File("line-item.xml");

???????? FileInputStream fis= new FileInputStream(file);

???????? XMLInputFactory xif= XMLInputFactory.newInstance();

???????? XMLStreamReader reader= xif.createXMLStreamReader(fis);

?

然后創建一個 builder 并將 XMLStreamReader 傳遞給它:

?? StAXOMBuilder builder= new StAXOMBuilder(reader);

???????? lineItem= builder.getDocumentElement();

?

現在可以使用 AXIOM API 來訪問屬性和子元素或者 XML Infoset 項了??梢赃@樣訪問屬性:

?? OMAttribute quantity= lineItem.getFirstAttribute(

???????? new QName("http://openuri.org/easypo", "quantity"));

?? System.out.println("quantity= " + quantity.getValue());

?

用類似的方式訪問子元素:

?? price= lineItem.getFirstChildWithName(

???????? new QName("http://openuri.org/easypo", "price"));

?????????????? System.out.println("price= " + price.getText());

?

清單 4 顯示了完整的代碼片段。


清單 4. XML 文件構建 AXIOM

?

File file = new File("line-item.xml");

?? FileInputStream fis = new FileInputStream(file);

?? XMLInputFactory xif = XMLInputFactory.newInstance();

?? XMLStreamReader reader = xif.createXMLStreamReader(fis);

?? StAXOMBuilder builder = new StAXOMBuilder(reader);

?? OMElement lineItem = builder.getDocumentElement();

?? lineItem.serializeWithCache(writer);

?? writer.flush();

?? OMAttribute quantity = lineItem.getFirstAttribute(

???????? new QName("http://openuri.org/easypo", "quantity"));

?? System.out.println("quantity= " + quantity.getValue());

?? OMElement price = lineItem.getFirstChildWithName(

???????? new QName("http://openuri.org/easypo", "price"));

?? System.out.println("price= " + price.getText());

?? OMElement description = lineItem.getFirstChildWithName(

???????? new QName("http://openuri.org/easypo", "description"));

?? System.out.println("description= " + description.getText());

?

AXIOM 最好的一點是,努力在延遲構造這類高端技術上提供用戶友好的 API。但是要充分發揮其潛能,必須了解底層體系結構。

?


?

?

?回頁首

?

?

?

進一步考察 AXIOM

緩沖是 AXIOM 的核心概念之一。但是,要理解緩沖必須在樹的延遲構造和 AXIOM API 上下文中來思考。AXIOM 提供多種訪問底層 XML Infoset 的 API。上面使用的是基于樹的 API,所有其他競爭的對象模型如 DOM 和 JDOM 都提供了這樣的 API。但是,AXIOM 還允許通過 SAX 或 StAX API 訪問信息。如圖 1 所示。


1. AXIOM,輸入和輸出

如果要使用一種 XML 解析 API,為何還要構造對象模型呢?為了使用不同 API 訪問對象模型的不同部分。比如,考慮 SOAP 棧的情況:SOAP 消息在被目標服務消費之前可能會經過多個處理程序的處理。這些處理程序通常使用基于樹的 API(特別是 SOAP with Attachments API for Java,或 SAAJ)。服務實現還可能使用數據綁定工具將 SOAP 消息負荷中的 XML 文檔轉化成對象,如 POJO。因為用戶不使用基于樹的對象模型來訪問這部分文檔,所以構造完整的樹會因為數據重復而浪費內存。最直接的解決方法是向數據綁定工具公開底層的原始 XML 流。這就是 AXIOM 的閃光之處。

為了獲得最佳的性能和內存使用,需要讓數據綁定工具直接訪問底層的 XML 流。AXIOM 完全允許這樣做。延遲構建僅僅意味著只有在訪問的時候才構造要訪問的這部分樹。因此如果不需要訪問 SOAP 消息體,SOAP 消息的這部分就不會被構建。如果用戶開始使用 SAX 或 StAX 訪問消息體,而它還沒有構建,AXIOM 將把用戶直接連接到底層的解析器,以便提供最佳的性能。如圖 2 所示:


2.通過 AXIOM 訪問底層的解析器

但是,如果用戶希望再回來訪問樹的同一部分就可能出現問題。因為解析器已經直接連接了用戶,AXIOM 退出了,就是說所有信息都從低層的流直接流向用戶。因此當用戶回來請求同樣的信息時,無論第二次選擇什么樣的 API,AXIOM 都不能提供該信息。注意這兩種可能性差不多相等。比如,多數情況下 SOAP 體的處理中只有最終的服務實現才會涉及到負荷。服務可以使用數據綁定或其他 XML 處理 API 如 SAX、StAX 或 XPath 來處理消息體。這種情況下,消息體很少被訪問兩次,AXIOM 提供的優化具有最好的性能。

但是,假設在處理程序鏈中插入一個日志處理程序,使用 StAX writer 記錄整個 SOAP 消息。如果服務實現嘗試訪問消息體,而消息體不存在!

為了進一步說明這一點,下面是一個比較簡單的例子,雖然有點牽強。

StAXOMBuilder builder = new StAXOMBuilder(reader);

?? lineItem = builder.getDocumentElement();

?? lineItem.serialize(writer);

?? writer.flush();

?? price = lineItem.getFirstChildWithName(

????? new QName("http://openuri.org/easypo", "price"));

?? System.out.println("price= " + price.getText());

?

由于延遲構造,獲得 lineItem 元素的時候該元素還沒有構造完成。因此后面使用 StAX writer 進行序列化時,AXIOM 把 StAX writer(它序列化 lineItem 元素)直接連接到 StAX reader(它最初被傳遞給 builder)。但是這個過程中,AXIOM 斷開了自身和數據流的連接。現在當請求 price 子元素的時候,找不到這樣的元素,因為 lineItem 的所有子元素都在序列化器中消失了。

這種情況下,惟一的辦法是避免序列化過程中 AXIOM 完全和數據流脫離開。用 AXIOM 的術語稱為緩沖:無論是否在內存中建立了對象模型,AXIOM 都允許獲得 StAX 事件或者 序列化 XML。因此,AXIOM 把策略(比如是否應該緩沖消息)和機制(如何緩沖)分離開來。它允許用戶在開始使用原始 XML 處理 API(如 SAX 或 StAX)時決定是否緩沖樹中未用到的部分以供將來引用。如果用戶決定這樣做,當樹構造完成時可以再回來訪問這些部分。但是,用戶必須付出內存占用和性能的代價。另一方面,如果用戶了解自己的目標,并確信只此一次需要訪問樹的這些部分,則可以選擇關閉 緩沖來充分發揮 AXIOM 的效率。

因此,上一段代碼應改寫為:

?? StAXOMBuilder builder = new StAXOMBuilder(reader);

????? lineItem = builder.getDocumentElement();

????? lineItem.serializeWithCache(writer);

????? writer.flush();

?? price = lineItem.getFirstChildWithName(

????? new QName("http://openuri.org/easypo", "price"));

?? System.out.println("price= " + price.getText());

?

方法 serializeWithCache 與對應的 serialize 不同,不會將 StAX reader 直接連接到 StAX writer。相反,從 reader 傳遞給 writer 的所有數據都保留 在 AXIOM 中。具體如何緩沖與用戶無關。目前如果啟用緩沖,AXIOM 就會像用戶在通過文檔 API 訪問樹的這些部分一樣構造樹。

?

?

?

AXIOM StAX

了解這些背景之后,現在看看 AXIO 的 StAX API。該 API 中最重要的方法如下:

(OMElement).getXMLStreamReader();

(OMElement).getXMLStreamReaderWithoutCaching();

?

通過 StAX API 對某個元素調用第一個方法,可以訪問該元素的 XML Infoset,同時緩沖(如果需要)樹中未構造的部分以供將來使用。顧名思義,第二個方法用于訪問同樣的信息,但是通過關閉緩沖機制優化了性能。在編寫需要使用數據綁定框架的存根和 skeleton 程序時,這是最有用的方法。

但是請注意,如果在調用上述方法之前已經建立了樹,AXIOM 將模擬 StAX 解析器。因此有些樹節點的事件是通過模擬而來的,而對于另一些節點則直接連接到底層的解析器。AXIOM 的優點在于這些內部處理對用戶是透明的。但是,在切換到原始 API 時,必須指明是否需要緩沖數據。

為了說明 StAX API 的用法,我將展示如何使用 XMLBeans 生成的代碼連接到 AXIOM。


清單 5.XMLBeans 生成的訂單代碼

?

public class PurchaseOrderSkel {

?? public void submitPurchaseOrder(

???????? PurchaseOrderDocument doc) throws Exception {

???????????????? ?

?? }

????? public void submitPurchaseOrderWrapper(

?????????????? OMElement payload) {

??????????? try {

??????? ??????????XMLStreamReader reader= payload.

??????????????????????? getXMLStreamReaderWithoutCaching();

????????????????? PurchaseOrderDocument doc

???????????????????? = PurchaseOrderDocument.Factory.parse(reader);

?????????????????????????? submitPurchaseOrder(doc);

??????????? } catch (Exception ex) {

????????????????? ex.printStacktrace();

??????????? }

????? }

?? }

?

清單 5 中的代碼(通常用代碼生成工具生成)展示了一個 skeleton,它使用 XMLBeans 生成的類(即 PurchaseOrderDocument)進行數據綁定。這個 skeleton 包含兩個服務實現方法。第一個允許服務實現者使用數據綁定對象,第二個則允許直接訪問 AXIOM API。主要看看這幾行:

????????????????? XMLStreamReader reader= payload.

??????????????????????? getXMLStreamReaderWithoutCaching();

????????????????? PurchaseOrderDocument doc

???????????????????? = PurchaseOrderDocument.Factory.parse(reader);

?

為了創建對象,首先對 SOAP 棧(如 Apache Axis)壓入服務實現的載荷獲得對 StAX API 的引用。因為現在在處理鏈的最末端,所以可以安全地把解析器直接連接到 XMLBeans 解除封送器以獲得最佳性能。

對于 清單 5 中的 skeleton,其存根代碼類似于 清單 6。


清單 6.存根代碼

?

public class PurchaseOrderStub {

???????? public void submitPurchaseOrder(

??????????? PurchaseOrderDocument doc) throws Exception {

????????????????? SOAPEnvelope envelope = factory.getDefaultEnvelope();

????????????????? XMLStreamReader reader = doc.newXMLStreamReader();

????????????????? StAXOMBuilder builder = new StAXOMBuilder(reader);

????????????????? OMElement payload= builder.getDocumentElement();

????????????????? envelope.getBody().addChild(payload);

????????????????? // ...

???????? }

????? }

?

主要看看這幾行:

????????????????? XMLStreamReader reader = doc.newXMLStreamReader();

????????????????? StAXOMBuilder builder = new StAXOMBuilder(reader);

????????????????? Element payload= builder.getDocumentElement();

?

從這段代碼可以看出,經過 StAX API 從對象到 AXIOM,與從 XML 到 AXIOM 沒有什么區別。

但是初看起來不那么明顯的是延遲構造仍然在起作用!即使在將載荷插入 SOAP 信封的過程中創建了 OMElement,內存中也沒有重復的信息項。這是由于延遲構造和 AXIOM 內的多路技術造成的,它將從一個 API 輸入的數據直接轉發給另一個 API 輸出。當消息最終寫入流的時候,XMLBeans 提供的 XMLStreamReader 直接連接到傳輸 writer,后者將消息寫入套接字 —— 假設此過程中沒有要查看消息的處理程序。這意味著直到此時,數據仍然存放在 XMLBeans 對象中,真是好極了!

?

?

?

AXIOM 和數據綁定

這里討論 AXIOM 的 SAX API,因為有些數據綁定框架不能使用其他的 API,比如 JAXB。雖然上述情況下使用 SAX 顯然不會達到最佳性能,但從 AXIOM 到對象使用 SAX 并沒有造成性能損失,因為這一步在任何情況下都是必需的。

如果使用 JAXB,那么存根程序就要使用 SAXOMBuilder 從數據綁定對象建立 AXIOM。清單 7 示范了這個過程。


清單 7. AXIOM JAXB

?

public class PurchaseOrderStub {

????? public void submitPurchaseOrder(

??????????? PurchaseOrder doc) throws Exception {

????????? ????????SOAPEnvelope envelope = factory.getDefaultEnvelope();

????????????????? SAXOMBuilder builder = new SAXOMBuilder();

????????????????? JAXBContext jaxbContext = JAXBContext.newInstance("po");

????????????????? Marshaller marshaller = jaxbContext.createMarshaller();

????????????????? marshaller.marshal(doc, builder);

????????????????? OMElement payload= builder.getDocumentElement();

????????????????? envelope.getBody().addChild(payload);

????????????????? //...

????? }

?? }

?

到目前為止,AXIOM 還不允許使用 OMElement 注冊內容處理程序來處理收到的 SAX 事件。不過很容易編寫一段膠水代碼,從提供的 StAX 接口接收事件并驅動 SAX ContentHandler。有興趣的讀者可以從 參考資料 中的 JAXB 參考實現中找到這樣的實現。

?

?

結束語

我介紹了與典型的 XML 對象模型相比 AXIOM 引入的一些很有前途的特性。注意本文僅僅介紹了部分特性。AXIOM 有很多更強大的特性,建議您從 Axis 2 源代碼庫(請參閱 參考資料)下載最新的源代碼,進一步研究 AXIOM。

?

參考資料

學習

    • 您可以參閱本文在 developerWorks 全球站點上的 英文原文。
    • 進一步了解這一技術,請閱讀 Eran Chinthaka 撰寫的文章“Introducing AXIOM: The Axis Object Model”(java.net,2005 年 5 月)。
    • 從 Apache Axis 2 官方網站上閱讀 AXIOM 教程。
    • Apache Axis 2 是下一代 Apache SOAP 棧實現,它使用 AXIOM 作為核心對象模型。該站點還包括 Axis 2 源代碼庫。
    • 看一看 Apache XMLBeans,即 XML 綁定框架,它與 AXIOM 直接耦合來為 Axis 2 提供數據綁定支持。
    • 參考 Sosnoski Software Solutions, Inc. 的 XMLBench Document Model Benchmark 程序。在 Apache Wiki 處可以找到本文所述的測試結果。
    • 進一步了解 StAX 請閱讀 JSR 173: Streaming API for XML,關于拉式解析的 Java 規范。XML.com 也提供了很有幫助的 StAX 教程。
    • 通過 Berthold Daum 撰寫的 developerWorks 系列技巧進一步了解 StAX:
      • “技巧: 使用 XML 流解析器”(2003 年 11 月)
      • “技巧: 使用 StAX 部分解析 XML 文檔”(2003 年 12 月)
      • “技巧: 使用 StAX 高效篩選 XML 文檔”(2003 年 12 月)
      • “技巧: 使用 StAX 編寫 XML 文檔”(2003 年 12 月)
      • “技巧: 使用 StAX 合并 XML 文檔”(2004 年 1 月)

?

轉載于:https://www.cnblogs.com/antis/p/5228191.html

總結

以上是生活随笔為你收集整理的转 用 AXIOM 促进 XML 处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。