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

歡迎訪問 生活随笔!

生活随笔

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

asp.net

用 AXIOM 促进 XML 处理

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

簡介:?AXis 對象模型(AXis Object Model,AXIOM)是 Apache Axis 2 的 XML 對象模型,其目標是提供強大的特性組合徹底改變 XML 處理技術。AXIOM 超越了現有的 XML 處理技術,它把延遲構建和一種快速、輕型的可定制對象模型結合了起來。本文中,軟件架構師、AXIOM 的首創者 Eran Chinthaka 介紹了這種新的 XML 處理方法。

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。

轉載于:https://www.cnblogs.com/chinacloud/archive/2010/10/28/1863168.html

總結

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

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