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

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

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

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

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

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


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

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

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

MSXML 提供了兩個(gè)差異很大的 XML 分析器。第一個(gè)分析器是在各種情形下可用的 DOM 實(shí)現(xiàn)。如果使用較小的 XML 文檔且需要隨機(jī)訪問 XML 文檔進(jìn)行內(nèi)存中讀取和寫入,則 DOM 實(shí)現(xiàn)是一種合理的選擇。MSXML 的更高版本引入了“用于 XML 的簡單 API (SAX2)”的實(shí)現(xiàn)。它實(shí)際上是否簡單是有爭議的。使用 SAX2 時(shí)(甚至在開始之前),您需要實(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 存在的問題以及 .NET Framework 不提供其實(shí)現(xiàn)的原因在于 SAX2 模型的內(nèi)在復(fù)雜性。它要求實(shí)現(xiàn)接口或事件,并強(qiáng)制開發(fā)人員使用更為間接的編程模型,要求開發(fā)人員管理注定會使應(yīng)用程序變得復(fù)雜的其他狀態(tài)。相反,.NET Framework 中的 XmlReader 和 XmlWriter 類以及 XmlLite 的 IXmlReader 和 IXmlWriter 接口提供了簡單易懂的分析器,可以直接在函數(shù)中使用,而不必管理任何外部狀態(tài)或通知。

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

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

Back to top

COM“Lite”

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

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

我在以下示例中使用 COM_VERIFY 宏,以便清晰地識別方法在何處返回需要檢查的 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 類模板確保迅速釋放接口指針。

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

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

CComPtr<IStream> stream;

// Create stream object here...

COM_VERIFY(reader->SetInput(stream));

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

設(shè)置 XML 讀取器的輸入后,可以通過重復(fù)調(diào)用 Read 方法進(jìn)行讀取。Read 方法接受一個(gè)可選參數(shù),該參數(shù)在每次成功調(diào)用時(shí)返回節(jié)點(diǎn)類型。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)的屬性,請使用 MoveToFirstAttribute 和 MoveToNextAttribute 方法。如果已成功地重新定位讀取器,則這兩種方法都返回 S_OK;如果不存在更多的屬性,則返回 S_FALSE。以下示例說明如何依次枚舉給定節(jié)點(diǎn)的屬性:

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

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

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

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ù)是可選的;如果它不為零,則它將返回以字符度量的字符串長度(不包括空結(jié)束符)。

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

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

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

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

寫入 XML

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

CComPtr<IXmlWriter> writer;

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

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

CComPtr<IStream> stream;

// Create stream object here

COM_VERIFY(writer->SetOutput(stream));

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

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

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

請考慮以下示例:

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 聲明寫入流的操作。它只有一個(gè)參數(shù),該參數(shù)接受來自 XmlStandalone 枚舉的值,指示是否出現(xiàn)獨(dú)立的文檔聲明,如果是這樣,則指示它保存的值。寫入 XML 片段時(shí),通常省略對 WriteStartDocument 的調(diào)用。

WriteStartElement 方法接受以下三個(gè)參數(shù):第一個(gè)參數(shù)指定元素的可選命名空間前綴,第二個(gè)參數(shù)指定元素的本地名稱,第三個(gè)參數(shù)指定可選的命名空間 URI。WriteElementString 是 XmlLite 提供的非常方便的方法之一。用于寫入 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 方法不是絕對必要的,但它確實(shí)很有用。

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

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

圖 3 寫入器
圖 3?寫入器
Back to top

使用流

到此為止,我對流進(jìn)行的介紹并不多。與一些功能更全面的 XML 庫不同,XmlLite 未提供任何支持從公共存儲位置(如文件或通過網(wǎng)絡(luò)協(xié)議)讀取和向其寫入的功能。正因?yàn)檫@一點(diǎn),對于希望從其讀取或向其寫入的任何存儲器,您都需要提供 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)存對象。以下示例創(chuàng)建一個(gè)由系統(tǒng)內(nèi)存支持且將根據(jù)需要?jiǎng)討B(tài)增長的 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)行寫入,但是如果在讀取時(shí)嘗試檢測文本編碼,則可以覆蓋此行為。首先,讓我們看一下您將自動(dòng)獲取的信息。對于給定的流,IXmlReader 將通過作為 XML 前同步碼的字節(jié)順序標(biāo)記來檢測編碼提示。IXmlReader 還將允許在 XML 聲明中指定的任何編碼。期望任何 XML 分析器都具有這兩個(gè)特征。如果具有可能未定義任何編碼信息的輸入流,而且 XmlLite 無法試探性地確定正使用的編碼,則可以將 IXmlReader 定向到特定的編碼(如果給定了代碼頁或編碼名稱)。

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

CComPtr<IStream> stream;

// Create stream object here

COM_VERIFY(reader->SetInput(stream));

要覆蓋編碼,請將代碼更改為:

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

Back to top

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

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

CComPtr<IStream> stream;

// Create stream object here

COM_VERIFY(writer->SetOutput(stream));

要覆蓋默認(rèn)編碼,請編寫以下代碼:

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

Back to top

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

為了在讀取大數(shù)據(jù)值時(shí)限制內(nèi)存使用,XML 讀取器提供了按數(shù)據(jù)塊讀取值的機(jī)制。IXmlReader ReadValueChunk 方法讀取的字符數(shù)不超過規(guī)定的最大字符數(shù),在預(yù)料到后續(xù)調(diào)用時(shí)向前移動(dòng)讀取器。以下示例說明如何重復(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ù)塊寫入 CString 對象。這僅僅是為了說明如何管理數(shù)據(jù)塊的長度,顯然這在實(shí)際中會抵消數(shù)據(jù)分塊的優(yōu)勢。

Back to top

安全注意事項(xiàng)

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

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

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

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

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

Back to top

總結(jié)

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

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

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

只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   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>
            亚洲精品在线免费观看视频| aa级大片欧美| 激情一区二区| 精品99一区二区| 亚洲国产精品成人| 亚洲精品日韩精品| 亚洲深夜福利在线| 亚洲欧美一区二区三区久久| 亚洲专区一区| 久久久久国内| 亚洲人成网站在线观看播放| 99re6热只有精品免费观看| 亚洲视频久久| 久久―日本道色综合久久| 免费成人黄色av| 国产精品久久午夜| 亚洲福利在线看| 亚洲日本精品国产第一区| 亚洲精品在线视频观看| 香蕉亚洲视频| 欧美精品尤物在线| 国产综合第一页| 亚洲免费电影在线观看| 久久精品亚洲热| 99国产精品99久久久久久| 久久爱www.| 国产精品成人免费精品自在线观看| 国产午夜精品视频| 亚洲视频一区| 亚洲二区视频在线| 欧美在线日韩精品| 欧美性天天影院| 亚洲精品乱码久久久久| 久久亚洲综合| 亚洲综合精品| 欧美日韩一区三区四区| 亚洲欧洲一区二区三区久久| 久久精品亚洲一区二区| 99精品视频网| 免费在线欧美视频| 黑丝一区二区三区| 久久国产精品久久久久久电车| 亚洲毛片在线免费观看| 蜜桃av噜噜一区二区三区| 国产精品一区二区三区观看| 亚洲视频 欧洲视频| 亚洲电影有码| 米奇777在线欧美播放| 黄网站色欧美视频| 久久视频在线看| 性伦欧美刺激片在线观看| 久久久精品性| 亚洲视频电影图片偷拍一区| 欧美激情中文字幕一区二区| 久久高清免费观看| 国产婷婷色一区二区三区| 亚洲综合精品自拍| 亚洲午夜久久久久久久久电影网| 欧美日韩一级视频| 亚洲一区精品视频| 亚洲亚洲精品三区日韩精品在线视频| 欧美精品乱码久久久久久按摩| 亚洲国产婷婷综合在线精品| 欧美激情亚洲激情| 欧美久久久久免费| 国产精品99久久久久久久vr| 日韩视频在线观看国产| 欧美三级特黄| 久久电影一区| 久久亚洲欧美国产精品乐播| 亚洲人午夜精品| 99精品欧美一区二区三区综合在线| 欧美日韩国产综合久久| 亚洲一区二区精品| 先锋影音久久久| 狠狠色2019综合网| 欧美国产成人在线| 欧美日韩亚洲精品内裤| 欧美一级视频一区二区| 久久精品国产69国产精品亚洲 | 国产精品99久久99久久久二8 | 欧美综合国产| 欧美在线综合| 亚洲精品免费观看| 亚洲自拍偷拍色片视频| 国内久久婷婷综合| 亚洲精品乱码久久久久久日本蜜臀| 欧美日韩不卡一区| 久久九九热免费视频| 老牛影视一区二区三区| 亚洲一级特黄| 久久一区二区三区超碰国产精品| 夜夜精品视频一区二区| 午夜性色一区二区三区免费视频| 亚洲国产精品久久人人爱蜜臀| 一本色道久久综合狠狠躁的推荐| 久久成人精品一区二区三区| 亚洲国产老妈| 亚洲欧美福利一区二区| 亚洲国产经典视频| 亚洲在线观看| 99re6热只有精品免费观看| 午夜精品久久| 在线亚洲一区| 可以看av的网站久久看| 亚洲一区二区三区午夜| 亚洲欧美中文日韩在线| 蜜桃av一区| 国产精品盗摄一区二区三区| 免费观看欧美在线视频的网站| 欧美日韩亚洲高清| 欧美激情在线播放| 激情综合色丁香一区二区| 在线一区二区三区做爰视频网站| 亚洲精品久久久久久久久久久久久| 欧美一区综合| 欧美在线亚洲在线| 国产精品欧美一区二区三区奶水 | 国产精品久久久久一区| 亚洲第一黄色| 韩国av一区二区| 亚洲欧美中文在线视频| 宅男噜噜噜66一区二区| 女人天堂亚洲aⅴ在线观看| 久久综合激情| 一区免费在线| 久久久五月天| 久热精品视频在线观看| 国产一区二区观看| 欧美一级在线亚洲天堂| 性色av一区二区三区| 国产精品毛片在线看| 亚洲手机在线| 午夜性色一区二区三区免费视频| 国产精品h在线观看| 一本一本久久a久久精品综合妖精| 日韩一级精品视频在线观看| 欧美高清视频www夜色资源网| 亚洲大片免费看| 亚洲精选久久| 欧美精品一区二区三区四区| 亚洲日本一区二区三区| 一区二区欧美在线| 国产精品r级在线| 亚洲综合社区| 久久久久久穴| 欧美不卡一卡二卡免费版| 欧美a级片一区| 国产精品婷婷午夜在线观看| 亚洲天堂成人| 久久国产精品一区二区三区四区| 国产偷久久久精品专区| 久久久久久亚洲精品中文字幕| 美女91精品| 在线亚洲+欧美+日本专区| 国产精品试看| 米奇777在线欧美播放| 99在线精品视频| 久久久国产午夜精品| 最新成人在线| 欧美另类高清视频在线| 亚洲一区二区成人在线观看| 久久躁日日躁aaaaxxxx| 亚洲毛片在线| 国产精品美女久久久| 久久高清国产| 99人久久精品视频最新地址| 久久九九免费视频| 99精品欧美一区二区三区| 国产欧美日韩亚洲一区二区三区| 久久综合色天天久久综合图片| 亚洲精品视频免费观看| 免费h精品视频在线播放| 亚洲欧美三级伦理| 国产亚洲精品成人av久久ww| 欧美激情亚洲视频| 久久gogo国模裸体人体| 亚洲日本欧美日韩高观看| 久久精品最新地址| 亚洲视频在线视频| 亚洲黄页一区| 国产一区日韩二区欧美三区| 欧美精品一区二区三区在线播放| 午夜精品一区二区三区在线播放| 亚洲国产精品成人综合色在线婷婷| 午夜国产不卡在线观看视频| 亚洲美女在线看| 激情久久久久久久| 国产精品久久久999| 欧美大胆a视频| 久久久久国产一区二区三区四区| 在线性视频日韩欧美| 亚洲激情视频| 欧美高清在线视频| 久久综合狠狠综合久久综合88 | 在线欧美电影| 狠狠网亚洲精品| 国产亚洲精品资源在线26u| 国产精品国产| 国产精品国产自产拍高清av王其|