青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-2  評(píng)論-2  文章-0  trackbacks-0
原文地址:http://msdn.microsoft.com/msdnmag/issues/07/04/Xml/Default.aspx?loc=zh

??? 盡管 .NET Framework 不斷取得成功,Microsoft 仍然認(rèn)真對(duì)待本機(jī) C++ 開(kāi)發(fā)。通過(guò)引入 XmlLite(適合于用本機(jī) C++ 編寫(xiě)的應(yīng)用程序的高性能、低開(kāi)銷(xiāo) XML 讀取器和寫(xiě)入器)說(shuō)明了這一點(diǎn)。

托管代碼通過(guò) System.Xml 命名空間廣泛支持 XML,而依賴(lài)于 COM 的傳統(tǒng) Visual Basic? 和 C++ 應(yīng)用程序可以訪問(wèn) Microsoft? XML 核心服務(wù) (MSXML) 中的類(lèi)似功能。但是,這些并沒(méi)有為需要快速精簡(jiǎn)的 XML 分析器的本機(jī) C++ 開(kāi)發(fā)人員提供富有吸引力的選項(xiàng)。開(kāi)始使用 XmlLite 吧。

本文將探討您可以對(duì) XmlLite 執(zhí)行的操作。但是,首先,為設(shè)定預(yù)期,我希望快速回顧一下 XmlLite 未提供的內(nèi)容,至少是此初始版本中未提供的內(nèi)容。對(duì)于初學(xué)者,它既未提供文檔對(duì)象模型 (DOM) 實(shí)現(xiàn),也未提供 XML 架構(gòu)或文檔類(lèi)型定義 (DTD) 驗(yàn)證。它還缺少對(duì)高級(jí)工具的支持,例如基于光標(biāo)的導(dǎo)航(如 XPath)、樣式表和序列化。但是,通過(guò)建立在 XmlLite 之上的功能,可以根據(jù)需要填補(bǔ)任何空白,Microsoft .NET Framework 中的幾乎所有 XML 功能同樣都建立在 XmlReader 和 XmlWriter 類(lèi)之上。

那么,XmlLite 提供了哪些內(nèi)容?簡(jiǎn)單地說(shuō),它提供了非緩存的只進(jìn)分析器(提供接收式編程模型)和非緩存的只進(jìn) XML 生成器。已證明這兩者是非常有價(jià)值的功能。


為什么推出新的 XML 分析器?

開(kāi)發(fā)人員日益熟悉他們每天使用的庫(kù),通過(guò)廣泛使用 XML,他們肯定會(huì)詢(xún)問(wèn)有關(guān)新推出的 XML 分析器的一些疑難問(wèn)題。要了解這一新分析器的價(jià)值,讓我們首先考慮一下 XML 分析器當(dāng)今的情形。

很自然地,如果應(yīng)用程序已經(jīng)利用 .NET Framework,則決定通常是很簡(jiǎn)單的:只需使用 System.Xml 即可。為證明這一點(diǎn),XmlLite 的設(shè)計(jì)基于 .NET Framework 中 XmlReader 和 XmlWriter 類(lèi)的設(shè)計(jì)。從以 C++ 編寫(xiě)的托管應(yīng)用程序使用 XmlLite 通常沒(méi)有優(yōu)勢(shì)。XmlLite 的功能畢竟比 XmlReader 和 XmlWriter 類(lèi)提供的功能要少得多。(圖?1 中的表略述 XmlLite 中的主要類(lèi)型如何映射到 .NET Framework 中的主要類(lèi)型。)另一方面,如果應(yīng)用程序僅使用本機(jī)代碼,那么就 Microsoft 技術(shù)而言,MSXML 在傳統(tǒng)上是所選的解決方案。

MSXML 提供了兩個(gè)差異很大的 XML 分析器。第一個(gè)分析器是在各種情形下可用的 DOM 實(shí)現(xiàn)。如果使用較小的 XML 文檔且需要隨機(jī)訪問(wèn) XML 文檔進(jìn)行內(nèi)存中讀取和寫(xiě)入,則 DOM 實(shí)現(xiàn)是一種合理的選擇。MSXML 的更高版本引入了“用于 XML 的簡(jiǎn)單 API (SAX2)”的實(shí)現(xiàn)。它實(shí)際上是否簡(jiǎn)單是有爭(zhēng)議的。使用 SAX2 時(shí)(甚至在開(kāi)始之前),您需要實(shí)現(xiàn)至少兩個(gè) COM 接口:一個(gè)用于接收 XML 文檔中各個(gè)節(jié)點(diǎn)的通知,另一個(gè)用于接收分析錯(cuò)誤的通知。

將 SAX2 實(shí)現(xiàn)添加到 MSXML 的原因如下:與 DOM 實(shí)現(xiàn)不同,SAX2 分析器以數(shù)據(jù)流形式讀取 XML 文檔,并通知您何時(shí)到達(dá)各個(gè)節(jié)點(diǎn)。這意味著,您的應(yīng)用程序的內(nèi)存使用量并不隨所分析文檔的大小而增加。

SAX2 存在的問(wèn)題以及 .NET Framework 不提供其實(shí)現(xiàn)的原因在于 SAX2 模型的內(nèi)在復(fù)雜性。它要求實(shí)現(xiàn)接口或事件,并強(qiáng)制開(kāi)發(fā)人員使用更為間接的編程模型,要求開(kāi)發(fā)人員管理注定會(huì)使應(yīng)用程序變得復(fù)雜的其他狀態(tài)。相反,.NET Framework 中的 XmlReader 和 XmlWriter 類(lèi)以及 XmlLite 的 IXmlReader 和 IXmlWriter 接口提供了簡(jiǎn)單易懂的分析器,可以直接在函數(shù)中使用,而不必管理任何外部狀態(tài)或通知。

由于其設(shè)計(jì)的簡(jiǎn)明性,XmlLite 能夠提供相當(dāng)好的性能,即使與 MSXML SAX2 實(shí)現(xiàn)相比也是如此。雖然 SAX2 分析器可以比 DOM 實(shí)現(xiàn)更好地處理大型文檔,但是與 XmlLite 相比就遜色了。

簡(jiǎn)單地說(shuō),XmlLite 優(yōu)于 MSXML,且它更易于從本機(jī) C++ 使用。MSXML 仍將是 Visual Basic 和基于 COM 的腳本語(yǔ)言的最可行解決方案,但是現(xiàn)在本機(jī) Visual C++? 最終具有了專(zhuān)門(mén)為它設(shè)計(jì)的 XML 分析器。雖然 Windows Vista? 和更高版本中附帶有 XmlLite,但是一個(gè)更新對(duì)于 Windows? XP 和 Windows Server? 2003 的 32 位和 64 位版本也是可用的。因?yàn)槲瓷婕?COM 注冊(cè),所以此更新包應(yīng)該不會(huì)導(dǎo)致 MSXML 通常造成的有關(guān)安裝和版本控制的難題。

Back to top

COM“Lite”

XmlLite 不僅是易記的名稱(chēng);事實(shí)上,它是一個(gè)輕型 XML 分析器。XmlLite 利用了 COM 的精華,即編程規(guī)范和約定,并拋棄了復(fù)雜的和可能不必要的部分,如 COM 注冊(cè)、運(yùn)行時(shí)服務(wù)、代理、線程模型、封送處理等。

從 XmlLite.dll 導(dǎo)出的函數(shù)創(chuàng)建 XML 讀取器和寫(xiě)入器。通過(guò)鏈接到 XmlLite.lib 并包括 Windows SDK 中的 XmlLite.h 頭文件,可以訪問(wèn)它們。生成的 COM 樣式接口使用熟悉的 IUnknown 接口方法進(jìn)行生存期管理。COM IStream 接口也起到一定作用并表示存儲(chǔ)器。除此之外,沒(méi)有 COM 的依賴(lài)項(xiàng);無(wú)需注冊(cè)任何 COM 類(lèi)或甚至調(diào)用強(qiáng)制性的 CoInitialize 函數(shù)。活動(dòng)模板庫(kù) (ATL) CComPtr 類(lèi)處理剩余的一小部分 COM。但是,您確實(shí)需要關(guān)注線程安全,因?yàn)槌鲇趩尉€程方案中的性能,XmlLite 不是線程安全的。

我在以下示例中使用 COM_VERIFY 宏,以便清晰地識(shí)別方法在何處返回需要檢查的 HRESULT。可以將此替換為相應(yīng)的錯(cuò)誤處理 - 不管該操作引發(fā)異常還是您自己返回 HRESULT。

Back to top

讀取 XML

XmlLite 提供了返回 IXmlReader 接口實(shí)現(xiàn)的 CreateXmlReader 函數(shù):

CComPtr<IXmlReader> reader;
COM_VERIFY(::CreateXmlReader(__uuidof(IXmlReader),
                             reinterpret_cast<void**>(&reader),
                             0));

雖然是可選的,但是 CComPtr 類(lèi)模板確保迅速釋放接口指針。

CreateXmlReader 接受接口標(biāo)識(shí)符 (IID) 以及指向 void 指針的指針。這是 COM 編程中的常見(jiàn)模式,允許調(diào)用方指定要返回的接口指針的類(lèi)型。我的示例使用 __uuidof 運(yùn)算符,該運(yùn)算符是 Microsoft 特定的關(guān)鍵字,用于提取與類(lèi)型關(guān)聯(lián)的 GUID。在這種情況下,它用于檢索接口的 IID。CreateXmlReader 的最后一個(gè)參數(shù)接受可選的 IMalloc 實(shí)現(xiàn)以允許調(diào)用方控制內(nèi)存分配。

創(chuàng)建讀取器后,需要指示讀取器將用作輸入的存儲(chǔ)器。IStream 接口表示存儲(chǔ)器,這樣就可以將 XmlLite 與可能設(shè)計(jì)的任何流實(shí)現(xiàn)一起使用:

CComPtr<IStream> stream;

// Create stream object here...

COM_VERIFY(reader->SetInput(stream));

(我將在本文的后面部分中討論流。)

設(shè)置 XML 讀取器的輸入后,可以通過(guò)重復(fù)調(diào)用 Read 方法進(jìn)行讀取。Read 方法接受一個(gè)可選參數(shù),該參數(shù)在每次成功調(diào)用時(shí)返回節(jié)點(diǎn)類(lèi)型。Read 方法返回 S_OK 以指示已從流中成功讀取下一個(gè)節(jié)點(diǎn),返回 S_FALSE 以指示已到達(dá)流的結(jié)尾處。以下是如何依次枚舉節(jié)點(diǎn)的一個(gè)示例:

HRESULT result = S_OK;
XmlNodeType nodeType = XmlNodeType_None;

while (S_OK == (result = reader->Read(&nodeType)))
{
    // Get node-specific info
}

要枚舉當(dāng)前節(jié)點(diǎn)的屬性,請(qǐng)使用 MoveToFirstAttribute 和 MoveToNextAttribute 方法。如果已成功地重新定位讀取器,則這兩種方法都返回 S_OK;如果不存在更多的屬性,則返回 S_FALSE。以下示例說(shuō)明如何依次枚舉給定節(jié)點(diǎn)的屬性:

for (HRESULT result = reader->MoveToFirstAttribute(); 
     S_OK == result;
     result = reader->MoveToNextAttribute())
{
    // Get attribute-specific info
}

調(diào)用 IXmlReader 的 Read 方法時(shí),它會(huì)將任何節(jié)點(diǎn)屬性自動(dòng)存儲(chǔ)在內(nèi)部集合中。這樣,您就可以使用 MoveToAttributeByName 方法,按名稱(chēng)將讀取器移動(dòng)到特定的屬性。但是,枚舉屬性并將其存儲(chǔ)在應(yīng)用程序特定的數(shù)據(jù)結(jié)構(gòu)中,效率通常更高。請(qǐng)注意,您還可以使用 GetAttributeCount 方法確定當(dāng)前節(jié)點(diǎn)中的屬性數(shù)。

確定節(jié)點(diǎn)或?qū)傩院螅@取其信息就很簡(jiǎn)單了。以下示例演示如何獲取給定節(jié)點(diǎn)的命名空間 URI 和本地名稱(chēng):

PCWSTR namespaceUri = 0;
UINT namespaceUriLength = 0;

COM_VERIFY(reader->GetNamespaceUri(&namespaceUri, 
                                   &namespaceUriLength));

PCWSTR localName = 0;
UINT localNameLength = 0;

COM_VERIFY(reader->GetLocalName(&localName, 
                                &localNameLength));

返回字符串值的所有 IXmlReader 方法都遵循此模式。第一個(gè)參數(shù)接受指向?qū)捵址羔槼A康闹羔槨5诙€(gè)參數(shù)是可選的;如果它不為零,則它將返回以字符度量的字符串長(zhǎng)度(不包括空結(jié)束符)。

以下是強(qiáng)調(diào)性能的另一個(gè)示例。僅在將讀取器移動(dòng)到其他節(jié)點(diǎn)或以某種其他方式(如通過(guò)設(shè)置新的輸入流或釋放 IXmlReader 接口)使當(dāng)前節(jié)點(diǎn)無(wú)效之前,從 IXmlReader 方法返回的字符串指針才是有效的。換句話說(shuō),IXmlReader 不會(huì)將流的副本返回給調(diào)用方。

與其在 .NET Framework 中的對(duì)應(yīng)方不同,IXmlReader 未提供讀取鍵入內(nèi)容的任何方法。例如,如果特定的元素或?qū)傩园瑪?shù)字或日期,則您需要首先獲取其字符串表示形式,然后根據(jù)需要自己進(jìn)行轉(zhuǎn)換。.NET Framework 的 XmlReader 類(lèi)中存在的許多其他 helper 方法也不存在于 IXmlReader 中,但是可以作為 helper 函數(shù)編寫(xiě)。XmlLite 確實(shí)符合最小接口設(shè)計(jì)的 C++ 理論。

圖?2 顯示使用 IXmlReader 讀取 XML 文檔時(shí)涉及的對(duì)象和抽象。但是,請(qǐng)牢記,IStream 可以抽取任何存儲(chǔ),此處顯示的文件僅僅是一個(gè)常見(jiàn)示例。

圖 2 讀取器
圖 2?讀取器
Back to top

寫(xiě)入 XML

XmlLite 提供了返回 IXmlWriter 接口實(shí)現(xiàn)的 CreateXmlWriter 函數(shù):

CComPtr<IXmlWriter> writer;

COM_VERIFY(::CreateXmlWriter(__uuidof(IXmlWriter),
                             reinterpret_cast<void**>(&writer),
                             0));

創(chuàng)建寫(xiě)入器后,需要指示寫(xiě)入器將用作輸出的存儲(chǔ)器:

CComPtr<IStream> stream;

// Create stream object here

COM_VERIFY(writer->SetOutput(stream));

開(kāi)始寫(xiě)入之前,可以修改寫(xiě)入器屬性。XmlWriterProperty 枚舉定義可用的屬性。例如,您可能希望指定是否縮進(jìn) XML 輸出以便于讀者閱讀(使用 SetProperty 方法可以做到這一點(diǎn)):

COM_VERIFY(writer->SetProperty(XmlWriterProperty_Indent, TRUE));

然后可以開(kāi)始使用 IXmlWriter 方法寫(xiě)入基礎(chǔ)流。XmlLite 支持 XML 片段。如果計(jì)劃寫(xiě)入完整的 XML 文檔,則應(yīng)該從調(diào)用 WriteStartDocument 方法(它負(fù)責(zé)寫(xiě)入 XML 聲明)開(kāi)始。聲明取決于所用的編碼,但是默認(rèn)編碼為 UTF-8,它在大多數(shù)情況下都應(yīng)該是合適的。(稍后將介紹文本編碼。)提供了許多 WriteXxx 方法,用于寫(xiě)入各種節(jié)點(diǎn)類(lèi)型、屬性和值。

請(qǐng)考慮以下示例:

COM_VERIFY(writer->WriteStartDocument(XmlStandalone_Omit));
COM_VERIFY(writer->WriteStartElement(0, L"html", 
                                     L"http://www.w3.org/1999/xhtml"));

COM_VERIFY(writer->WriteStartElement(0, L"head", 0));
COM_VERIFY(writer->WriteElementString(0, L"title", 0, L"My Web Page"));
COM_VERIFY(writer->WriteEndElement()); // </head>

COM_VERIFY(writer->WriteStartElement(0, L"body", 0));
COM_VERIFY(writer->WriteElementString(0, L"p", 0, L"Hello world!"));

COM_VERIFY(writer->WriteEndDocument());

WriteStartDocument 方法處理將 XML 聲明寫(xiě)入流的操作。它只有一個(gè)參數(shù),該參數(shù)接受來(lái)自 XmlStandalone 枚舉的值,指示是否出現(xiàn)獨(dú)立的文檔聲明,如果是這樣,則指示它保存的值。寫(xiě)入 XML 片段時(shí),通常省略對(duì) WriteStartDocument 的調(diào)用。

WriteStartElement 方法接受以下三個(gè)參數(shù):第一個(gè)參數(shù)指定元素的可選命名空間前綴,第二個(gè)參數(shù)指定元素的本地名稱(chēng),第三個(gè)參數(shù)指定可選的命名空間 URI。WriteElementString 是 XmlLite 提供的非常方便的方法之一。用于寫(xiě)入 XHTML 文檔標(biāo)題的以下代碼等效于上一示例中使用的 WriteElementString:

COM_VERIFY(writer->WriteStartElement(0, L"title", 0));
COM_VERIFY(writer->WriteString(L"My Web Page"));
COM_VERIFY(writer->WriteEndElement());

顯然,WriteElementString 方法不是絕對(duì)必要的,但它確實(shí)很有用。

最后,WriteEndDocument 方法用于關(guān)閉文檔。您可能已注意到,未顯式關(guān)閉 body 和 html 元素。WriteEndDocument 會(huì)自動(dòng)關(guān)閉任何打開(kāi)的元素。就此而言,釋放寫(xiě)入器也會(huì)關(guān)閉任何剩余的元素。但是,如果您不小心,則未顯式關(guān)閉此類(lèi)元素的做法可能會(huì)導(dǎo)致錯(cuò)誤,因?yàn)榱鞯纳嫫诤蛯?xiě)入器的生存期通常可以不同。要說(shuō)的是,如果需要確保已將所有要寫(xiě)入的內(nèi)容寫(xiě)入基礎(chǔ)流,則只需調(diào)用 IXmlWriter 的 Flush 方法即可。

圖?3 顯示使用 IXmlWriter 寫(xiě)入 XML 文檔時(shí)涉及的對(duì)象和抽象流。請(qǐng)牢記,IStream 可以抽取任何存儲(chǔ),此處的文件僅僅是一個(gè)常見(jiàn)示例。

圖 3 寫(xiě)入器
圖 3?寫(xiě)入器
Back to top

使用流

到此為止,我對(duì)流進(jìn)行的介紹并不多。與一些功能更全面的 XML 庫(kù)不同,XmlLite 未提供任何支持從公共存儲(chǔ)位置(如文件或通過(guò)網(wǎng)絡(luò)協(xié)議)讀取和向其寫(xiě)入的功能。正因?yàn)檫@一點(diǎn),對(duì)于希望從其讀取或向其寫(xiě)入的任何存儲(chǔ)器,您都需要提供 IStream 實(shí)現(xiàn)。實(shí)現(xiàn) IStream 接口并不復(fù)雜,但是在許多情況下,您不需要執(zhí)行此操作,因?yàn)閷?shí)現(xiàn)可能已存在。

CreateStreamOnHGlobal 函數(shù)提供由虛擬內(nèi)存支持的 IStream 實(shí)現(xiàn)。第一個(gè)參數(shù)是使用 GlobalAlloc 函數(shù)創(chuàng)建的可選內(nèi)存句柄。但是,只需傳遞零,CreateStreamOnHGlobal 即可為您創(chuàng)建內(nèi)存對(duì)象。以下示例創(chuàng)建一個(gè)由系統(tǒng)內(nèi)存支持且將根據(jù)需要?jiǎng)討B(tài)增長(zhǎng)的 IStream 實(shí)現(xiàn):

CComPtr<IStream> stream;
COM_VERIFY(::CreateStreamOnHGlobal(0, TRUE, &stream));

釋放流將釋放內(nèi)存。

SHCreateStreamOnFile 函數(shù)提供了另一個(gè)有用的 IStream 實(shí)現(xiàn)。它創(chuàng)建由文件支持的 IStream:

CComPtr<IStream> stream;
COM_VERIFY(::SHCreateStreamOnFile(L"D:\\Sample.xml",
                                  STGM_WRITE | STGM_SHARE_DENY_WRITE,
                                  &stream));

Back to top

讀取時(shí)的文本編碼

雖然默認(rèn)情況下 XmlLite 使用 UTF-8 進(jìn)行寫(xiě)入,但是如果在讀取時(shí)嘗試檢測(cè)文本編碼,則可以覆蓋此行為。首先,讓我們看一下您將自動(dòng)獲取的信息。對(duì)于給定的流,IXmlReader 將通過(guò)作為 XML 前同步碼的字節(jié)順序標(biāo)記來(lái)檢測(cè)編碼提示。IXmlReader 還將允許在 XML 聲明中指定的任何編碼。期望任何 XML 分析器都具有這兩個(gè)特征。如果具有可能未定義任何編碼信息的輸入流,而且 XmlLite 無(wú)法試探性地確定正使用的編碼,則可以將 IXmlReader 定向到特定的編碼(如果給定了代碼頁(yè)或編碼名稱(chēng))。

可以假借 IXmlReaderInput 接口創(chuàng)建 XML 讀取器輸入對(duì)象,而不是將流直接傳遞到 IXmlReader。提供了兩個(gè)用于創(chuàng)建包裝輸入流的輸入對(duì)象的函數(shù)。CreateXmlReaderInputWithEncodingCodePage 函數(shù)接受代碼頁(yè)編號(hào)形式的代碼。CreateXmlReaderInputWithEncodingName 函數(shù)接受使用其規(guī)范名稱(chēng)的編碼。除此之外,這兩個(gè)函數(shù)具有完全相同的簽名。概括一下,通常可以對(duì) XML 讀取器的輸入流進(jìn)行如下設(shè)置:

CComPtr<IStream> stream;

// Create stream object here

COM_VERIFY(reader->SetInput(stream));

要覆蓋編碼,請(qǐng)將代碼更改為:

CComPtr<IStream> stream;

// Create stream object here

CComPtr<IXmlReaderInput> input;

COM_VERIFY(::CreateXmlReaderInputWithEncodingName(stream,
                                                  0, // default allocator
                                                  L"ISO-8859-8",
                                                  TRUE, // hint
                                                  0, // base URI
                                                  &input));

COM_VERIFY(reader->SetInput(input));

第一個(gè)參數(shù)指示 XML 讀取器將從其讀取的流。第二個(gè)參數(shù)接受可選的 IMalloc 實(shí)現(xiàn)。如果提供的話,則它將覆蓋 XML 讀取器自己的實(shí)現(xiàn)。第三個(gè)參數(shù)指定編碼名稱(chēng)。msdn2.microsoft.com/ms752827.aspx 上的文檔列出了本機(jī)支持的編碼;要支持其他編碼,可以提供 IMultiLanguage2 接口實(shí)現(xiàn)。下一個(gè)參數(shù)指示是否必須使用指定的編碼或者它是否僅僅是一個(gè)提示。如果指定 TRUE,則指示分析器嘗試使用建議的編碼,但是如果它失敗,則可以隨意嘗試試探性地確定實(shí)際的編碼。如果指定 FALSE,則指示分析器嘗試建議的編碼;如果它與輸入流不匹配,則返回錯(cuò)誤。下一個(gè)參數(shù)接受可能用于解析外部實(shí)體的可選基本 URI。最后一個(gè)參數(shù)返回表示要傳遞到 SetInput 方法的輸入對(duì)象的接口指針。

Back to top

寫(xiě)入時(shí)的文本編碼

XML 寫(xiě)入器將基于傳遞到 SetOutput 方法的對(duì)象確定要使用的編碼。如果該對(duì)象實(shí)現(xiàn) IStream 接口或者甚至實(shí)現(xiàn)有限的 ISequentialStream 接口,則 XML 寫(xiě)入器將使用 UTF-8 編碼。可以創(chuàng)建 XML 寫(xiě)入器輸出對(duì)象來(lái)覆蓋此行為。提供了兩個(gè)用于創(chuàng)建包裝輸出流的輸出對(duì)象的函數(shù)。CreateXmlWriterOutputWithEncodingCodePage 函數(shù)接受代碼頁(yè)編號(hào)形式的編碼,而 CreateXmlWriterOutputWithEncodingName 函數(shù)接受使用其規(guī)范名稱(chēng)的編碼。除此之外,這兩個(gè)函數(shù)具有完全相同的簽名。通常,可以對(duì) XML 寫(xiě)入器的輸出流進(jìn)行如下設(shè)置:

CComPtr<IStream> stream;

// Create stream object here

COM_VERIFY(writer->SetOutput(stream));

要覆蓋默認(rèn)編碼,請(qǐng)編寫(xiě)以下代碼:

CComPtr<IStream> stream;

// Create stream object here

CComPtr<IXmlWriterOutput> output;

COM_VERIFY(::CreateXmlWriterOutputWithEncodingName(stream,
                                                   0,
                                                   L"ISO-8859-8",
                                                   &output));

COM_VERIFY(writer->SetOutput(output));

第一個(gè)參數(shù)指示 XML 寫(xiě)入器將寫(xiě)入的流。第二個(gè)參數(shù)接受可選的 IMalloc 實(shí)現(xiàn)。如果提供的話,則它將覆蓋 XML 寫(xiě)入器自己的實(shí)現(xiàn)。第三個(gè)參數(shù)指定編碼名稱(chēng)。最后一個(gè)參數(shù)返回表示要傳遞到 SetOutput 方法的輸出對(duì)象的接口指針。

Back to top

處理大數(shù)據(jù)值

為了在讀取大數(shù)據(jù)值時(shí)限制內(nèi)存使用,XML 讀取器提供了按數(shù)據(jù)塊讀取值的機(jī)制。IXmlReader ReadValueChunk 方法讀取的字符數(shù)不超過(guò)規(guī)定的最大字符數(shù),在預(yù)料到后續(xù)調(diào)用時(shí)向前移動(dòng)讀取器。以下示例說(shuō)明如何重復(fù)調(diào)用 ReadValueChunk 以讀取大數(shù)據(jù)值:

CString value;

WCHAR chunk[256] = { 0 };
HRESULT result = S_OK;
UINT charsRead = 0;

while (S_OK == (result = reader->ReadValueChunk(chunk,
                                                countof(chunk),
                                                &charsRead)))
{
    value.Append(chunk, charsRead);
}

當(dāng)不再有數(shù)據(jù)可用時(shí),ReadValueChunk 返回 S_FALSE。在此示例中,我要將數(shù)據(jù)塊寫(xiě)入 CString 對(duì)象。這僅僅是為了說(shuō)明如何管理數(shù)據(jù)塊的長(zhǎng)度,顯然這在實(shí)際中會(huì)抵消數(shù)據(jù)分塊的優(yōu)勢(shì)。

Back to top

安全注意事項(xiàng)

以 XML 為中心的應(yīng)用程序必須總是處理來(lái)自不可信源的 XML。XmlLite 提供了許多工具以保護(hù)應(yīng)用程序免受已知漏洞和將來(lái)漏洞的攻擊。

XML 文檔可以包含對(duì)外部實(shí)體的引用。一些 XML 分析器自動(dòng)解析這些實(shí)體。雖然此方法可能很有用,但是,如果未仔細(xì)編寫(xiě) XML 解析程序以緩解各種威脅,則此方法可能會(huì)造成安全漏洞的攻擊。XmlLite 既不自動(dòng)解析外部實(shí)體,也不提供 XML 解析程序。要提供自己的實(shí)現(xiàn)(如有必要),請(qǐng)實(shí)現(xiàn) IXmlResolver 接口并將 XmlReaderProperty_XmlResolver 屬性與 IXmlReader SetProperty 方法一起使用,以指示讀取器使用您的解析程序。

XML 文檔可能還包含 DTD 處理說(shuō)明。雖然 XmlLite 不支持文檔驗(yàn)證(使用 XML 架構(gòu)或 DTD),但是它支持 DTD 實(shí)體擴(kuò)展和默認(rèn)屬性。由于這些 DTD 可以包含對(duì)外部實(shí)體的引用,因此它們可能會(huì)使您的應(yīng)用程序受到各種攻擊。默認(rèn)情況下,XmlLite 禁用 DTD 處理。通過(guò)將 XmlReaderProperty_DtdProcessing 屬性設(shè)置為 DtdProcessing_Parse 值,可以允許 DTD 處理。此外,還存在由 XmlReaderProperty_MaxEntityExpansion 控制的 DTD 實(shí)體擴(kuò)展攻擊(也稱(chēng)為 billion laughs 攻擊)的內(nèi)置緩解措施。此屬性的默認(rèn)值為 100,000。

攻擊者可以利用使用 XML 的應(yīng)用程序的另一種方法是,創(chuàng)建名稱(chēng)非常長(zhǎng)的文檔。如果未能阻止,則這可能用盡巨大的內(nèi)存并允許拒絕服務(wù)攻擊。我已經(jīng)提示了可以執(zhí)行的方法。緩解此類(lèi)威脅的一種明顯方法是,按數(shù)據(jù)塊讀取大數(shù)據(jù)值,如上一部分所述。另一種有用的方法是,提供限制內(nèi)存分配的自定義 IMalloc 實(shí)現(xiàn)。如果輸入流支持隨機(jī)訪問(wèn),則還可以指示 XML 讀取器使用 XmlReaderProperty_RandomAccess 屬性來(lái)避免緩存屬性。這將減少用于讀取開(kāi)始元素標(biāo)記的內(nèi)存量,但是也可能降低分析速度,因?yàn)榉治銎鞅仨殎?lái)回查找以便在請(qǐng)求時(shí)檢索各個(gè)屬性值。

如果 XML 層次結(jié)構(gòu)過(guò)深,則也可能快速用盡系統(tǒng)資源。要阻止攻擊者提供層次結(jié)構(gòu)過(guò)深的 XML 文檔,可以使用 XmlReaderProperty_MaxElementDepth 屬性限制分析器將允許的深度。此屬性默認(rèn)為 256。

Back to top

總結(jié)

XmlLite 為本機(jī) C++ 應(yīng)用程序提供了功能強(qiáng)大的 XML 分析器。它著重于性能,知道它所使用的系統(tǒng)資源,為控制這些特征提供了很大的靈活性。XmlLite 支持所有的常見(jiàn)文本編碼,是一種非常有用的實(shí)用工具,可以簡(jiǎn)化本機(jī) C++ 應(yīng)用程序中的 XML 使用。有關(guān)詳細(xì)信息,請(qǐng)參閱 msdn2.microsoft.com/ms752872.aspx 上的 XmlLite 文檔。

posted on 2007-03-31 16:50 Canny 閱讀(1075) 評(píng)論(2)  編輯 收藏 引用

評(píng)論:
# re: 用于本機(jī) C++ 的小巧快捷的 XML 分析器 2007-04-01 08:40 | 空明流轉(zhuǎn)
COM啊。。。這點(diǎn)我還是比較的喜歡TinyXML。功能差不多也就夠了。。。  回復(fù)  更多評(píng)論
  
# re: 用于本機(jī) C++ 的小巧快捷的 XML 分析器 2007-04-16 13:40 | 復(fù)合管個(gè)
直接拷貝別人的文章有意思嗎?  回復(fù)  更多評(píng)論
  

只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久成人精品一区二区三区| 欧美国产日韩一区二区在线观看| 久久精品国产精品亚洲精品| 亚洲在线播放电影| 一区二区三区久久精品| 亚洲视频中文字幕| 性高湖久久久久久久久| 欧美一区激情| 欧美www视频在线观看| 亚洲国产成人精品久久| 欧美激情精品久久久久久| 亚洲电影下载| 亚洲视频免费在线观看| 欧美一区二区免费观在线| 久久午夜视频| 一区二区三区在线观看视频| 免费成人美女女| 欧美精品少妇一区二区三区| 国产精品红桃| 激情综合色综合久久| 亚洲欧洲一区二区在线播放| 亚洲五月婷婷| 裸体素人女欧美日韩| 亚洲精品综合久久中文字幕| 欧美亚洲在线观看| 欧美精品粉嫩高潮一区二区 | 欧美mv日韩mv国产网站| 欧美国产专区| 国产在线乱码一区二区三区| 99国产精品私拍| 久久狠狠亚洲综合| 亚洲精品久久久一区二区三区| 亚洲已满18点击进入久久 | 欧美日韩二区三区| 国内激情久久| 午夜国产精品视频免费体验区| 欧美jizzhd精品欧美喷水| 亚洲午夜久久久久久久久电影院| 母乳一区在线观看| 国产亚洲欧洲997久久综合| 99re6这里只有精品| 老司机午夜精品视频在线观看| 一区二区三区不卡视频在线观看| 久久婷婷国产综合精品青草| 国产精品日日摸夜夜添夜夜av| 亚洲欧洲美洲综合色网| 久久久久这里只有精品| 亚洲一区二区三区影院| 欧美喷潮久久久xxxxx| 一区二区视频免费在线观看| 欧美一级在线播放| 亚洲网站在线看| 欧美日本国产一区| 最新日韩在线视频| 欧美va亚洲va香蕉在线| 久久精品国产视频| 国产综合第一页| 久久国内精品视频| 久久岛国电影| 伊人夜夜躁av伊人久久| 久久久免费精品视频| 小黄鸭精品aⅴ导航网站入口| 国产精品激情av在线播放| 亚洲欧美日韩久久精品| 一区二区三区四区蜜桃| 欧美丝袜一区二区| 午夜免费在线观看精品视频| 亚洲欧美激情一区二区| 国产欧美一区二区色老头 | 这里是久久伊人| 欧美日韩卡一卡二| 在线一区二区日韩| 一本色道久久综合| 国产精品亚洲综合久久| 欧美一区二区三区日韩视频| 亚洲一区二区伦理| 国产日韩欧美亚洲一区| 久久男人资源视频| 麻豆精品一区二区av白丝在线| 亚洲国产日韩欧美一区二区三区| 亚洲欧洲精品一区二区三区| 欧美三区免费完整视频在线观看| 亚洲欧美日本日韩| 性色av一区二区三区在线观看| 国产在线精品二区| 亚洲国产精品一区在线观看不卡| 欧美日韩国产欧| 久久精品九九| 欧美精品精品一区| 欧美影院视频| 欧美电影免费观看| 午夜视频在线观看一区| 久久午夜av| 亚洲在线日韩| 久久综合给合久久狠狠狠97色69| 一区二区高清视频在线观看| 亚洲欧美日韩网| 亚洲伦理一区| 欧美在线观看一区二区| 一本色道久久综合亚洲精品高清 | 欧美乱妇高清无乱码| 性欧美激情精品| 欧美激情精品久久久久久大尺度| 欧美一区二区三区在| 男人的天堂亚洲在线| 翔田千里一区二区| 欧美精品综合| 欧美成人精品高清在线播放| 国产精品亚洲成人| 亚洲日本电影| 亚洲国内高清视频| 久久精品人人| 久久国产精品一区二区三区| 欧美日韩国产精品一区| 欧美高清免费| 黄色一区二区在线观看| 亚洲男女自偷自拍图片另类| 一本色道久久综合亚洲精品小说 | 久久精品国产一区二区三区免费看| 欧美精品午夜| 亚洲高清网站| 136国产福利精品导航网址| 亚洲欧美视频在线观看视频| 中文av一区二区| 欧美精品偷拍| 亚洲人精品午夜| 亚洲精品日日夜夜| 免播放器亚洲一区| 欧美亚洲视频在线观看| 亚洲视频一区二区| 欧美日韩国产天堂| 91久久精品一区二区三区| 曰本成人黄色| 久久一区二区视频| 免费观看成人| 伊人蜜桃色噜噜激情综合| 久久电影一区| 麻豆国产精品va在线观看不卡| 国产日韩欧美三区| 久久aⅴ国产欧美74aaa| 久久中文精品| 91久久中文| 欧美日韩国产美| 日韩视频中文| 午夜日韩av| 国产在线精品自拍| 麻豆成人综合网| 亚洲日本免费电影| 亚洲一区欧美二区| 国产欧美一区二区精品忘忧草| 午夜视频久久久久久| 久久全国免费视频| 伊人久久亚洲美女图片| 欧美激情精品久久久| 日韩一区二区免费高清| 亚洲一区二区动漫| 国产伪娘ts一区| 老色鬼久久亚洲一区二区 | 玖玖综合伊人| 亚洲第一色在线| 欧美成人一区二区在线 | 午夜精品区一区二区三| 国产女优一区| 嫩模写真一区二区三区三州| 亚洲精品乱码久久久久久日本蜜臀| 亚洲视屏一区| 激情综合电影网| 欧美日韩激情网| 亚洲欧美中文日韩在线| 欧美大色视频| 欧美亚洲三级| 亚洲精品欧美| 国产日本欧洲亚洲| 欧美国产大片| 欧美一区二区三区日韩视频| 亚洲福利专区| 久久久久久亚洲精品杨幂换脸| 99re视频这里只有精品| 国产一二三精品| 国产精品高潮粉嫩av| 久久伊人一区二区| 亚洲影院免费观看| 亚洲精品久久久久久一区二区| 久久久国产精品一区二区中文| 999亚洲国产精| 亚洲国产精品专区久久| 国产精品美女| 欧美成人免费网| 久久xxxx精品视频| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 日韩视频免费观看高清完整版| 国产精品久久久久婷婷| 麻豆精品一区二区综合av| 亚洲日本欧美在线| 欧美日韩国产成人在线免费| 久久精品毛片| 久久av一区二区三区漫画| 亚洲视频在线二区| 亚洲精品一区在线观看| 国产色视频一区|