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

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

??? 盡管 .NET Framework 不斷取得成功,Microsoft 仍然認(rèn)真對(duì)待本機(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 吧。

本文將探討您可以對(duì) XmlLite 執(zhí)行的操作。但是,首先,為設(shè)定預(yù)期,我希望快速回顧一下 XmlLite 未提供的內(nèi)容,至少是此初始版本中未提供的內(nèi)容。對(duì)于初學(xué)者,它既未提供文檔對(duì)象模型 (DOM) 實(shí)現(xiàn),也未提供 XML 架構(gòu)或文檔類型定義 (DTD) 驗(yàn)證。它還缺少對(duì)高級(jí)工具的支持,例如基于光標(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,他們肯定會(huì)詢問有關(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ā)人員管理注定會(huì)使應(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è)更新對(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 不僅是易記的名稱;事實(shí)上,它是一個(gè)輕型 XML 分析器。XmlLite 利用了 COM 的精華,即編程規(guī)范和約定,并拋棄了復(fù)雜的和可能不必要的部分,如 COM 注冊(cè)、運(yùn)行時(shí)服務(wù)、代理、線程模型、封送處理等。

從 XmlLite.dll 導(dǎo)出的函數(shù)創(chuàng)建 XML 讀取器和寫入器。通過鏈接到 XmlLite.lib 并包括 Windows SDK 中的 XmlLite.h 頭文件,可以訪問它們。生成的 COM 樣式接口使用熟悉的 IUnknown 接口方法進(jìn)行生存期管理。COM IStream 接口也起到一定作用并表示存儲(chǔ)器。除此之外,沒有 COM 的依賴項(xiàng);無需注冊(cè)任何 COM 類或甚至調(diào)用強(qiáng)制性的 CoInitialize 函數(shù)。活動(dòng)模板庫 (ATL) CComPtr 類處理剩余的一小部分 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 類模板確保迅速釋放接口指針。

CreateXmlReader 接受接口標(biāo)識(shí)符 (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)建讀取器后,需要指示讀取器將用作輸入的存儲(chǔ)器。IStream 接口表示存儲(chǔ)器,這樣就可以將 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)的屬性,請(qǐng)使用 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í),它會(huì)將任何節(jié)點(diǎn)屬性自動(dòng)存儲(chǔ)在內(nèi)部集合中。這樣,您就可以使用 MoveToAttributeByName 方法,按名稱將讀取器移動(dòng)到特定的屬性。但是,枚舉屬性并將其存儲(chǔ)在應(yīng)用程序特定的數(shù)據(jù)結(jié)構(gòu)中,效率通常更高。請(qǐng)注意,您還可以使用 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 不會(huì)將流的副本返回給調(diào)用方。

與其在 .NET Framework 中的對(duì)應(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í)涉及的對(duì)象和抽象。但是,請(qǐng)牢記,IStream 可以抽取任何存儲(chǔ),此處顯示的文件僅僅是一個(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)建寫入器后,需要指示寫入器將用作輸出的存儲(chǔ)器:

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)類型、屬性和值。

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

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

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

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

使用流

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

可以假借 IXmlReaderInput 接口創(chuàng)建 XML 讀取器輸入對(duì)象,而不是將流直接傳遞到 IXmlReader。提供了兩個(gè)用于創(chuàng)建包裝輸入流的輸入對(duì)象的函數(shù)。CreateXmlReaderInputWithEncodingCodePage 函數(shù)接受代碼頁編號(hào)形式的代碼。CreateXmlReaderInputWithEncodingName 函數(shù)接受使用其規(guī)范名稱的編碼。除此之外,這兩個(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ù)指定編碼名稱。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

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

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

CComPtr<IStream> stream;

// Create stream object here

COM_VERIFY(writer->SetOutput(stream));

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

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 方法的輸出對(duì)象的接口指針。

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 對(duì)象。這僅僅是為了說明如何管理數(shù)據(jù)塊的長度,顯然這在實(shí)際中會(huì)抵消數(shù)據(jù)分塊的優(yōu)勢。

Back to top

安全注意事項(xiàng)

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

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

XML 文檔可能還包含 DTD 處理說明。雖然 XmlLite 不支持文檔驗(yàn)證(使用 XML 架構(gòu)或 DTD),但是它支持 DTD 實(shí)體擴(kuò)展和默認(rèn)屬性。由于這些 DTD 可以包含對(duì)外部實(shí)體的引用,因此它們可能會(huì)使您的應(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)榉治銎鞅仨殎砘夭檎乙员阍谡?qǐng)求時(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ì)信息,請(qǐng)參閱 msdn2.microsoft.com/ms752872.aspx 上的 XmlLite 文檔。

posted @ 2007-03-31 16:50 Canny 閱讀(1075) | 評(píng)論 (2)編輯 收藏
  2007年3月17日

整型:
C++ 基本整型 為? char?、 short、? int、? long? 其中每種類型都有有符號(hào)版本和無符號(hào)版本。因此總共有8種類型可供選擇。
C++ 對(duì)長度的規(guī)定
short 至少 16位
int 至少和short 一樣長
long 至少32位,且至少要和int 一樣長。

無符號(hào)版本? 在 前面添加關(guān)鍵字? unsigned
unsigned short?????????? unsigned int?? unsigned long???????????? ,如果 只是 unsigned? 就是? unsigned int 的簡寫。

posted @ 2007-03-17 19:28 Canny| 編輯 收藏
僅列出標(biāo)題  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美成人高清视频| 国产欧美一区二区三区在线老狼 | 国产综合香蕉五月婷在线| 欧美在线视频一区二区| 亚洲午夜一区二区三区| 亚洲综合99| 久久精品免费电影| 美国成人直播| 欧美日韩国产91| 国产精品麻豆va在线播放| 国产精品美腿一区在线看 | 亚洲电影免费| 99在线精品视频在线观看| 亚洲视频 欧洲视频| 久久www成人_看片免费不卡| 你懂的一区二区| 99精品欧美一区二区三区| 亚洲男人影院| 欧美电影电视剧在线观看| 国产精品入口麻豆原神| 亚洲第一精品夜夜躁人人躁| 在线视频免费在线观看一区二区| 欧美一区影院| 91久久精品国产| 亚洲全部视频| 欧美亚洲在线视频| 欧美二区乱c少妇| 国产精品久久久久一区二区| 亚洲国产专区| 久久国产视频网| 亚洲精品资源美女情侣酒店| 久久久综合网站| 国产精品萝li| 亚洲精品一区二区三区四区高清| 欧美在线一二三四区| 亚洲激情综合| 久久久久久69| 国产精品一区二区三区四区| 99在线精品视频| 欧美福利视频一区| 午夜国产不卡在线观看视频| 欧美日韩www| 亚洲黄色天堂| 欧美不卡在线视频| 久久精品盗摄| 国产一区二区三区免费不卡| 性欧美暴力猛交69hd| 99精品国产福利在线观看免费| 欧美成人黑人xx视频免费观看| 在线观看欧美精品| 久久久久亚洲综合| 亚洲欧美一区二区三区久久| 国产精品免费观看视频| 亚洲一区二区三区高清| 99在线精品免费视频九九视| 欧美美女福利视频| 99精品欧美一区二区三区| 欧美激情成人在线视频| 欧美资源在线观看| ●精品国产综合乱码久久久久| 欧美制服第一页| 亚洲一区久久久| 国产精品白丝黑袜喷水久久久| 亚洲人久久久| 欧美国产一区在线| 久久躁狠狠躁夜夜爽| 在线观看国产欧美| 老司机午夜精品视频| 欧美一区日本一区韩国一区| 国产亚洲精品久久久久婷婷瑜伽| 亚洲一区一卡| 99精品欧美一区二区蜜桃免费| 国产精品国产三级国产aⅴ9色| 亚洲一级黄色片| 亚洲一区二区av电影| 国产精品每日更新在线播放网址| 国产精品99久久久久久有的能看 | 免费观看亚洲视频大全| 久久久久久久久久久一区 | 久久综合国产精品| 玖玖视频精品| 亚洲视频二区| 中文一区字幕| 欧美日精品一区视频| 欧美一进一出视频| 久久久久高清| 一区二区国产日产| 午夜久久影院| 亚洲毛片播放| 午夜精品亚洲一区二区三区嫩草| 欧美手机在线视频| 欧美一区二区日韩一区二区| 久久久久久久一区二区| 一区二区三区精品国产| 欧美亚洲在线视频| 亚洲开发第一视频在线播放| 亚洲网站在线| 亚洲经典一区| 亚洲一区免费观看| 亚洲欧洲精品一区二区三区| 亚洲一区二三| 亚洲精品视频啊美女在线直播| 亚洲男人的天堂在线| 亚洲精品乱码久久久久久日本蜜臀| 亚洲视频在线一区| 最新精品在线| 欧美一区影院| 亚洲欧美日韩中文在线制服| 免费在线亚洲欧美| 久久精品国产一区二区电影 | 欧美理论在线播放| 久久亚洲综合网| 国产精品久久久久久影视| 欧美国产日本高清在线| 欧美国产精品v| 国产亚洲一区二区三区| 免费成人在线观看视频| 国产精品综合视频| 亚洲日本欧美| 亚洲国产成人精品视频| 亚洲欧美综合国产精品一区| 亚洲视频日本| 欧美精品一区二区三区四区| 欧美风情在线观看| 曰本成人黄色| 久久婷婷一区| 久久中文字幕一区二区三区| 国产欧美日韩亚洲一区二区三区| 99在线热播精品免费| 亚洲国产精彩中文乱码av在线播放 | 国产手机视频一区二区| 99视频精品全部免费在线| 亚洲国产高清一区| 久久一二三国产| 老司机精品视频网站| 狠狠色狠狠色综合人人| 香蕉免费一区二区三区在线观看| 欧美一区二区三区电影在线观看| 国产欧美日韩视频在线观看| 欧美一区二区免费| 久久久久久亚洲精品中文字幕 | 欧美日精品一区视频| 亚洲精选视频免费看| 一本色道**综合亚洲精品蜜桃冫| 欧美日韩第一页| 这里只有视频精品| 小黄鸭精品密入口导航| 国产精品久久影院| 午夜日本精品| 看片网站欧美日韩| 亚洲国产裸拍裸体视频在线观看乱了| 久久综合九色综合网站| 亚洲成色777777女色窝| 亚洲国产欧美一区| 欧美极品在线播放| 亚洲视频在线观看| 欧美一区二区三区在线播放| 激情校园亚洲| 欧美福利精品| 亚洲一区二区三区高清| 久久久人成影片一区二区三区| 亚洲国产裸拍裸体视频在线观看乱了中文 | 欧美v国产在线一区二区三区| 欧美国产综合一区二区| 一区二区三区福利| 国产欧美精品一区二区色综合 | 亚洲性图久久| 久久亚洲二区| 欧美va日韩va| 亚洲精品黄色| 亚洲欧美日韩一区在线| 韩日视频一区| 欧美日韩中国免费专区在线看| 午夜欧美电影在线观看| 亚洲国产精品一区二区尤物区| 亚洲欧美中文日韩v在线观看| 国产综合色产在线精品| 欧美激情在线| 久久精品免费播放| 一区二区三区四区五区视频 | 快射av在线播放一区| 99re66热这里只有精品3直播| 国产美女精品免费电影| 美女精品网站| 亚欧美中日韩视频| 亚洲福利视频在线| 亚洲综合色婷婷| 91久久午夜| 国产精品视频不卡| 欧美伦理一区二区| 亚洲影音先锋| 亚洲每日在线| 亚洲福利电影| 欧美xx69| 久久中文精品| 久久精品视频99| 亚洲欧美精品伊人久久| 99成人免费视频| 91久久综合| 亚洲国产第一页|