一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

使用 MSXML 分析器處理 XML 文檔

 shaolong007 2005-09-29
 

使用 MSXML 分析器處理 XML 文檔

發(fā)布日期: 8/6/2004 | 更新日期: 8/6/2004

Kenn Scribner

Kenn Scribner 近期有關(guān) XML MSXML DOM 分析器的文章中,僅介紹了該分析器的部分功能。這些文章將 XML 作為一種技術(shù)進(jìn)行了說明,但是并沒有介紹 XML 分析器本身?,F(xiàn)在,Kenn 將回過頭來介紹 MSXML 分析器,并講解處理 XML 文檔和節(jié)點(diǎn)所需的基本知識:搜索特定的節(jié)點(diǎn)、插入節(jié)點(diǎn)和檢索節(jié)點(diǎn)值。

*

MSXML 分析器基于 XML 文檔對象模型,對于查看表 1 中所示的各種文檔對象來說,它非常重要。這些對象直接出自 XML 規(guī)范本身。MSXML 還可以進(jìn)一步將 XML DOM 對象合并到 COM 中。因此,弄清楚哪個 XML DOM 對象對應(yīng)于哪個 MSXML COM 接口非常容易。例如,IXMLDOMNode 代表稱為 Node 的 DOM 對象。

表 1. XML DOM 對象及其用途
DOM 對象 用途

DOMImplementation

一個查詢對象,用于確定 DOM 支持的級別

DocumentFragment

表示樹的一部分(可進(jìn)行剪切/粘貼操作)

Document

表示樹中的頂級節(jié)點(diǎn)

NodeList

用于訪問 XML 節(jié)點(diǎn)的 Iterator 對象

Node

用于擴(kuò)展帶核心 XML 標(biāo)記的元素

NamedNodeMap

命名空間支持和迭代通過屬性節(jié)點(diǎn)集合

CharacterData

文本操作對象

Attr

表示元素的屬性

Element

表示 XML 元素的節(jié)點(diǎn)(可用于訪問屬性)

Text

表示給定元素或?qū)傩詫ο蟮奈谋緝?nèi)容

CDATASection

用于屏蔽 XML 部分,使其不受分析和驗(yàn)證

Notation

包含基于 DTD 或架構(gòu)內(nèi)的表示法

Entity

表示已分析或未分析的實(shí)體

EntityReference

表示實(shí)體引用節(jié)點(diǎn)

ProcessingInstruction

表示處理指令

雖然有時比較容易混淆,但是 XML 文檔對象可以是(并且通常是)多態(tài)的。即,“節(jié)點(diǎn)”同時也是一個“元素”。當(dāng)您試圖確定需要何種 DOM 對象來執(zhí)行何種操作時,這有時會造成混淆。可以使用“文檔”對象來創(chuàng)建 DOM“節(jié)點(diǎn)”,但是,如果要向新創(chuàng)建的節(jié)點(diǎn)添加屬性,就必須通過其作為“元素”的一面來訪問它。如果說存在一種將對象和操作關(guān)聯(lián)在一起的神奇模式,那么我還沒能從自己的日常工作中將它提煉出來。我發(fā)現(xiàn)自己仍需要不斷參考 MSDN 文檔來查看哪個 COM 接口提供了所需的方法以執(zhí)行我試圖完成的任務(wù)。各種對象方法看上去的確是按邏輯分組的,這也正是我對 DOM 當(dāng)初的開發(fā)模式的推斷(通過分組邏輯操作)。

因此,其中的訣竅就在于從 MSXML 分析器檢索適當(dāng)?shù)?DOM 對象,這一操作的具體實(shí)現(xiàn)就是 COM 對象。操作的基本模式將是:首先實(shí)例化 MSXML COM 對象本身的一個副本,然后從該副本請求或以其他方式獲取指向附加 XML DOM 對象(本身也是 COM 對象)的指針。

MSXML DOM 試驗(yàn)應(yīng)用程序

創(chuàng)建一個漂亮的應(yīng)用程序,演示眾多的 MSXML 功能,這很簡單,但實(shí)際上,附加的代碼只會畫蛇添足。相反,我選擇了開發(fā)一個簡單的基于控制臺的應(yīng)用程序,該應(yīng)用程序執(zhí)行四種基本操作:

從磁盤加載一個 XML 文件。

搜索特定的節(jié)點(diǎn),并向該節(jié)點(diǎn)插入一個子節(jié)點(diǎn)。

搜索另一個節(jié)點(diǎn),并顯示該節(jié)點(diǎn)內(nèi)包含的(文本)值。

將修改后的 XML 文檔保存回磁盤中。

為了進(jìn)一步簡化,我硬編碼了 XML 文檔文件的名稱和 XML 節(jié)點(diǎn)本身。當(dāng)然,如果這是一個真實(shí)的應(yīng)用程序,您可能很少(或者永遠(yuǎn)不會)采用這樣的方法。但是在本例中,進(jìn)行這些權(quán)衡,是為了簡化圍繞在 MSXML 功能兩邊的代碼。

像平常一樣,在示例應(yīng)用程序中,我選擇了使用 ATL 來包裝許多與 COM 有關(guān)的活動。您肯定看到我使用了 CComPtr 和 CComQIPtr 對象,但是我還額外加入了幾個 CComBSTR 和 CComVariant 對象。如果您不熟悉它們,只需要記住它們是用于處理一些細(xì)節(jié)的模板,這些細(xì)節(jié)對于本文的主旨來說并非至關(guān)重要,但是從更廣的角度講,還是比較重要的。真正重要的是看到如何搜索 XML 節(jié)點(diǎn),添加新的(具有屬性的)節(jié)點(diǎn),以及顯示節(jié)點(diǎn)內(nèi)包含的文本。

我的基于控制臺的應(yīng)用程序可以在附帶的 下載文件中找到,它將加載一個名為 xmldata.xml 的 XML 文檔文件(假定其與可執(zhí)行文件位于同一個目錄中),并假定該文檔包含以下 XML 數(shù)據(jù):

<?xml version="1.0"?>
<xmldata>
   <xmlnode />
   <xmltext>Hello, World!</xmltext>
</xmldata>

我們將首先搜索 xmlnode 節(jié)點(diǎn),如果找到了該節(jié)點(diǎn),我們將插入一個新的(帶有屬性的)節(jié)點(diǎn)作為其子級。生成的 XML 文檔將為:

<?xml version="1.0"?>
<xmldata>
   <xmlnode>
      <xmlchildnode xml="fun" />
   </xmlnode>
   <xmltext>Hello, World!</xmltext>
</xmldata>

打印 節(jié)點(diǎn)內(nèi)包含的信息 ("Hello, World!") 之后,我們將把該新 XML 文檔保存到名為 updatedxml.xml 的文件中。然后,就可以使用文本編輯器或 Internet Explorer 5.x 來查看結(jié)果?,F(xiàn)在讓我們轉(zhuǎn)到代碼。

應(yīng)用程序首先初始化了 COM 運(yùn)行庫,然后創(chuàng)建了 MSXML 分析器的一個實(shí)例:

CComPtr<IXMLDOMDocument> spXMLDOM;
HRESULT hr = spXMLDOM.CoCreateInstance(
                __uuidof(DOMDocument));
if ( FAILED(hr) ) 
    throw "Unable to create XML parser object";
if ( spXMLDOM.p == NULL ) 
    throw "Unable to create XML parser object";

如果創(chuàng)建分析器實(shí)例成功,接下來,我們將把 XML 文檔加載到分析器中:

VARIANT_BOOL bSuccess = false;
hr = spXMLDOM->load(CComVariant(L"xmldata.xml"),
                    &bSuccess);
if ( FAILED(hr) ) 
   throw "Unable to load XML document into the parser";
if ( !bSuccess ) 
   throw "Unable to load XML document into the parser";

搜索節(jié)點(diǎn)與文檔對象有關(guān),因此,我們將使用 IXMLDOMDocument::selectSingleNode() 來根據(jù)其名稱查找特定的 XML 節(jié)點(diǎn)。其他的技巧很多,但是如果準(zhǔn)確地知道要查找的節(jié)點(diǎn)的名稱,這是最直接的方法:

CComBSTR bstrSS(L"xmldata/xmlnode");
CComPtr<IXMLDOMNode> spXMLNode;
hr = spXMLDOM->selectSingleNode(bstrSS,&spXMLNode);
if ( FAILED(hr) ) 
   throw "Unable to locate ‘xmlnode‘ XML node";
if ( spXMLNode.p == NULL ) 
   throw "Unable to locate ‘xmlnode‘ XML node";

一些您應(yīng)當(dāng)了解的其他方法包括 IXMLDOMDocument::nodeFromID() 和 IXMLDOMElement::getElementsByTagName(),使用它們可以獲得文檔中的節(jié)點(diǎn)的列表。您還可以將文檔作為樹來進(jìn)行訪問,并依次通過它(獲取子節(jié)點(diǎn),獲取同輩節(jié)點(diǎn)等)。

任一種情況下,搜索的結(jié)果都是一個 MSXML 節(jié)點(diǎn)對象 IXMLDOMNode。文檔中必須存在該節(jié)點(diǎn),否則搜索將失敗。我的應(yīng)用程序使用該節(jié)點(diǎn)作為一個全新 XML 節(jié)點(diǎn)的父級,該新節(jié)點(diǎn)是由 XML 文檔對象創(chuàng)建的:

CComPtr<IXMLDOMNode> spXMLChildNode;
hr = spXMLDOM->createNode(CComVariant(NODE_ELEMENT),
                          CComBSTR("xmlchildnode"),
                          NULL,
                          &spXMLChildNode);
if ( FAILED(hr) ) 
   throw "Unable to create ‘xmlchildnode‘ XML node";
if ( spXMLChildNode.p == NULL ) 
   throw "Unable to create ‘xmlchildnode‘ XML node";

如果分析器可以創(chuàng)建該節(jié)點(diǎn),下一步就是將它放到 XML 樹中。IXMLDOMNode::appendChild() 正是完成這一任務(wù)的方法:

CComPtr<IXMLDOMNode> spInsertedNode;
hr = spXMLNode->appendChild(spXMLChildNode,
                            &spInsertedNode);
if ( FAILED(hr) ) 
   throw "Unable to move ‘xmlchildnode‘ XML node";
if ( spInsertedNode.p == NULL ) 
   throw "Unable to move ‘xmlchildnode‘ XML node";

如果父節(jié)點(diǎn)的確將新創(chuàng)建的節(jié)點(diǎn)插入為其子級,將返回另一個 IXMLDOMNode 實(shí)例,該實(shí)例表示新的子節(jié)點(diǎn)。實(shí)際上,該新子節(jié)點(diǎn)和傳遞給 appendChild() 的節(jié)點(diǎn)是同一個 XML 節(jié)點(diǎn)。由于在存在問題時附加的子節(jié)點(diǎn)的指針將為 Null,因此,檢查該指針很有用。

到目前為止,我找到了一個特定的節(jié)點(diǎn),并為它創(chuàng)建了一個新的子節(jié)點(diǎn),下面,讓我們看看如何處理屬性。假定您要將該屬性添加到新的子節(jié)點(diǎn):

xml="fun"

這并不難,但是您必須從 IXMLDOMNode 切換到 IXMLDOMElement,以便訪問該子節(jié)點(diǎn)的元素特征。在實(shí)踐中,這意味著您必須查詢 IXMLDOMNode 接口的相關(guān) IXMLDOMElement 接口,查明后,再調(diào)用 IXMLDOMElement::setAttribute():

CComQIPtr<IXMLDOMElement> spXMLChildElement;
spXMLChildElement = spInsertedNode;
if ( spXMLChildElement.p == NULL ) 
   throw "Unable to query for ‘xmlchildnode‘ XML _
element interface";

hr = spXMLChildElement->setAttribute(CComBSTR(L"xml"),
                                CComVariant(L"fun"));
if ( FAILED(hr) ) 
   throw "Unable to insert new attribute";

此時,已經(jīng)修改了 XML 樹,并創(chuàng)建了所需的樹。應(yīng)用程序可以在這個時候?qū)⑽臋n保存到磁盤,或者執(zhí)行其他任務(wù)。現(xiàn)在,讓我們來搜索另一個節(jié)點(diǎn)并顯示該節(jié)點(diǎn)所包含的值(文本)。您已經(jīng)了解了如何搜索節(jié)點(diǎn),因此,我們將直接講解數(shù)據(jù)提取。

提取節(jié)點(diǎn)數(shù)據(jù)的關(guān)鍵在于使用 IXMLDOMNode::get_nodeTypedValue()。可以使用 Microsoft 數(shù)據(jù)類型架構(gòu)來標(biāo)識節(jié)點(diǎn)所包含的數(shù)據(jù),因此可以方便地存儲浮點(diǎn)值、整數(shù)、字符串或該架構(gòu)所支持的任何數(shù)據(jù)類型??梢允褂?dt:type 屬性來指定數(shù)據(jù)類型,如下所示:

<model dt:type="string">SL-2</model>
<year dt:type="int">1992</year>

如果特定的節(jié)點(diǎn)具有指定的數(shù)據(jù)類型,就可以使用 get_nodeTypedValue() 以該格式提取數(shù)據(jù)。如果未指定數(shù)據(jù)類型,將假定數(shù)據(jù)為文本,分析器將返回具有 BSTR 數(shù)據(jù)的 VARIANT。在本例中,這沒有任何問題,因?yàn)槲覀円阉鞯墓?jié)點(diǎn)是一個實(shí)際上包含一個字符串的文本節(jié)點(diǎn)。在需要時,始終可以使用 atoi() 等方法將字符串轉(zhuǎn)換為其他形式。本例中,我們只是提取該字符串?dāng)?shù)據(jù)并顯示它:

CComVariant varValue(VT_EMPTY);
hr = spXMLNode->get_nodeTypedValue(&varValue);
if ( FAILED(hr) ) 
   throw "Unable to retrieve ‘xmltext‘ text";

if ( varValue.vt == VT_BSTR ) {
   // Display the results...since we‘re not using the
   // wide version of the STL, we need to convert the
   // BSTR to ANSI text for display...
   USES_CONVERSION;
   LPTSTR lpstrMsg = W2T(varValue.bstrVal);
   std::cout << lpstrMsg << std::endl;
} 
else {
   // Some error
   throw "Unable to retrieve ‘xmltext‘ text";
} 

如果能夠檢索與節(jié)點(diǎn)關(guān)聯(lián)的值,并且該值為 BSTR(預(yù)期的數(shù)據(jù)類型),我們將在屏幕上顯示該文本。如果不能,將顯示一條錯誤消息,不過,根據(jù)情況而定,可以方便地采取其他操作。

最后一項(xiàng)與 XML 有關(guān)的操作是將已更新的 XML 樹保存到磁盤,這一任務(wù)是使用 IXMLDOMDocument::save() 完成的:

hr = spXMLDOM->save(CComVariant("updatedxml.xml"));
if ( FAILED(hr) ) 
   throw "Unable to save updated XML document";

完成保存后,向屏幕寫一條簡短說明,并退出。

這個示例應(yīng)用程序無論如何都算不上漂亮。您可以讓自己的應(yīng)用程序執(zhí)行很多其他功能,但我希望您通過這個簡短的示例了解到了如何從 C++ 程序使用 MSXML 分析器。該分析器本身是一個復(fù)雜的軟件,無論怎樣強(qiáng)調(diào)使用 MSDN Library 作為參考,都不能算是過份。該分析器公開了許多接口,這些接口通常會公開許多方法。即便如此,我在自己的項(xiàng)目中仍頻繁地使用該分析器,在親自編寫了一些代碼并進(jìn)行試驗(yàn)后,我發(fā)現(xiàn)這個軟件制作很精良 并且便于使用。我希望您也同樣會發(fā)現(xiàn)該分析器和一般意義上的 XML 具有廣泛的用途。

要了解有關(guān) Visual C++ Developer 和 Pinnacle Publishing 的更多信息,請?jiān)L問他們的 Web 站點(diǎn),網(wǎng)址為: http://www./

注:這不是 Microsoft Corporation 的網(wǎng)站。Microsoft 對該網(wǎng)站內(nèi)容不承擔(dān)責(zé)任。

本文復(fù)制自 Visual C++ Developer 的 2000 年 11 月刊。版權(quán)所有 2000,Pinnacle Publishing, Inc.(除非另行說明)。保留所有權(quán)利。Visual C++ Developer 是 Pinnacle Publishing, Inc. 獨(dú)立發(fā)行的產(chǎn)品。未經(jīng) Pinnacle Publishing, Inc. 事先同意,不得以任何形式使用或復(fù)制本文的任何部分(評論文章中的簡短引用除外)。要聯(lián)系 Pinnacle Publishing, Inc.,請致電 1-800-788-1900。

轉(zhuǎn)到原英文頁面


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产超薄黑色肉色丝袜| 色婷婷日本视频在线观看| 亚洲一区二区精品免费视频| 国产亚洲欧美自拍中文自拍| 国产毛片av一区二区三区小说| 日韩精品综合免费视频| 亚洲国产91精品视频| 日本免费熟女一区二区三区| 亚洲a级一区二区不卡| 亚洲免费观看一区二区三区| 日韩精品成区中文字幕| 九九热国产这里只有精品| 国产精品视频久久一区| 欧美日韩少妇精品专区性色| 成人精品欧美一级乱黄| 日本人妻丰满熟妇久久| 欧美自拍系列精品在线| 国产午夜精品在线免费看| 精品国产一区二区欧美| 国产精品偷拍视频一区| 男人的天堂的视频东京热| 厕所偷拍一区二区三区视频| 欧美日韩国产综合特黄| 丰满人妻一二区二区三区av| 中文字幕日韩欧美亚洲午夜| 爱在午夜降临前在线观看| 91国内视频一区二区三区| 精品国产亚洲免费91| 中文字幕精品一区二区年下载| 中文字幕精品一区二区年下载| 亚洲精品国产福利在线| 日本精品视频一二三区| 亚洲一区二区三区在线免费| 亚洲中文在线观看小视频| 欧洲一级片一区二区三区| 女人精品内射国产99| 色一欲一性一乱—区二区三区| 日韩欧美二区中文字幕| 国产欧美韩日一区二区三区| 国产一区一一一区麻豆| 免费国产成人性生活生活片|