當前位置:編程學習大全網 - 源碼下載 - VC6.0可以使用MSXML嗎?

VC6.0可以使用MSXML嗎?

在VC6中使用MSXML 4.0 DOM處理XML文檔

1. DOM與XML

DOM是Document Object Model的縮寫,提供了與XML交互的標準編程模型:(1)提供了標準方法在程序中創建、遍歷或者更新XML文檔內容。(2)提供了壹組核心的與供應商和語言無關的應用程序編程接口(API),可滿足與XML交互的大部分需求。因此,DOM APIs成為應用程序和XML文檔之間互通的橋梁。

W3C(World Wide Web Consortium)DOM Level 1規範定義了兩組DOM編程接口:6U6Linux聯盟

(1)基本接口:W3C基本接口定義了用來在應用程序中操縱XML文檔的接口;6U6Linux聯盟

(2)擴展接口:W3C擴展接口定義了壹些方便開發者的接口。

所有XML處理程序必須支持Unicode字符編碼的兩種形式:UTF-8和UTF-16。XML Parser可以讀取使用ISO-8859-1、Big-5或者Shift-JIS編碼的文檔,並在加載文檔時將它們自動轉換為Unicode。

如果XML文檔使用的字符編碼不是UTF-8(8-bit ASCII文本也是可接受的UTF-8)或者UTF-16,那麽它必須在XML聲明中提供字符編碼聲明,否則XML Parser可能會出錯。當然,即使對字符編碼進行了聲明,Parser也可能不能夠處理(不支持該編碼),但能夠正確地給出提示信息。(由於XML聲明是使用基本的ASCII文本書寫的,Parser能夠正確地讀出它的內容。)

2. MSXML 4.0簡介

MSXML(Microsoft XML Core Services)是Microsoft提供的用於處理XML文檔的COM庫。MSXML DOM不僅實現了W3C DOM Level 1規範定義的基本接口和擴展接口,還提供了額外的方法來支持XSL Transformation(XSLT)、XPath、名字空間和數據類型。MSXML除了支持規範所要求的字符編碼外,還支持更多的字符編碼格式,而在內部使用Unicode UCS-2字符編碼處理XML文檔中的所有文本。

本文以Visual C++ 6.0為開發環境,介紹MSXML4.0 SDK中DOM的使用。另外,MSXML中的SAX也比較常用。

2.1. MSXML DOM

MSXML DOM是本文介紹的重點,它提供了豐富的接口方便在程序中操作XML文檔。DOM在內存中提供了XML文檔的完整表示,允許對整個文檔內容的隨機訪問。 DOM允許應用程序依賴於MSXML Parser提供的邏輯結構來處理基於XML的信息。其工作流程和原理如下圖所示(源自MSXML 4.0 SDK):

當MSXML Parser把壹個XML文檔加載進DOM時,它從頭到尾讀入整個XML文檔,並構建內在邏輯樹結構。文檔本身被認為是包含其它所有節點的單個節點,例如,它包含根元素(Root Element),而根元素則包含文檔中所有的元素、屬性和文本節點。

MSXML DOM樹中每壹個節點都有特定的類型(如元素、屬性、文本),也有指向父節點和子節點的成員。其中,屬性節點是壹個特殊的節點,它不是子節點,是元素的屬性。

2.2. MSXML SAX2

有時,使用SAX(Simple API for XML)來解決XML應用可能是壹個更好的選擇。DOM方式允許開發者利用MSXML維護的DOM樹,而不用自己來管理。但有時,開發者需要更高的效率時,可能只需要讀入XML文檔,而在程序內部構造數據結構來管理XML文檔信息,這時就可以選擇SAX方式。下圖是MSXML SAX2的工作流程和原理圖(源自MSXML 4.0 SDK):

3. 安裝MSXML 4.0 SDK

早期的MSXML版本,特別是MSXML 2.5和MSXML 3.0,借助於xmlinst.exe工具,可以以替換模式進行安裝。在替換模式下,新安裝的MSXML版本替換舊版本,從而變成缺省的XML Parser。當妳在程序中使用版本無關的CLSID和ProgID時,缺省的XML Parser就被調用。這常常引起舊程序的兼容性問題。基於這個原因,MSXML 4.0只能以Side-by-side模式進行安裝。Xmlinst.exe工具在MSXML 4.0中不再提供,也不適用於MSXML 4.0。

MSXML 4.0 SDK(Microsoft XML Core Services 4.0 Software Development Ket)是以side-by-side模式安裝在妳的機器上的。這種模式有助於保護那些使用msxml.dll、msxml2.dll,或者 msxml3.dll的應用程序,使其不受幹擾,仍可照常使用。Side-by-side模式允許妳決定使用哪個版本的Parser來為妳工作,這可在妳的代碼中指定。6U6Linux聯盟

從Microsoft XML Download Center下載回安裝程序,安裝程序將在妳的機器上安裝三個文件:msxml4.dll、msxml4a.dll和msxml4r.dll,並對msxml4.dll進行註冊。

或者,妳也可以手動安裝MSXML,如果妳樂意的話。首先,拷貝上面的三個dll文件到機器的系統目錄($sysRoot\system32),壹般是 C:\WINDOWS\system32;然後,運行cmd,執行命令:(1) cd C:\WINDOWS\system32 (2) regsvr32 msxml4.dll。6U6Linux聯盟

在安裝MSXML 4.0 SDK後,應用程序必須使用版本相關的CLSID和ProgID來顯式地實例化Parser,這確保妳的應用程序的穩定性。

4. 使用MSXML DOM

本節介紹在VC6.0中使用MSXML DOM處理XML文檔。下面的示例中將動態生成壹個XML文檔,並對文檔進行查詢。

4.1. 導入MSXML

首先,需要導入MSXML頭文件和庫到VC6.0工程中。有兩種導入方式:6U6Linux聯盟

(1)自動方式,在源代碼中添加如下兩行程序即可:6U6Linux聯盟

#import <msxml4.dll>6U6Linux聯盟

using namespace MSXML2;6U6Linux聯盟

(2)手動方式(有存在的理由麽?呵呵)6U6Linux聯盟

a)找到MSXML 4.0 SDK的安裝目錄,去發現兩個子目錄inc和lib;6U6Linux聯盟

b)在VC選項中,將MSXML 4.0下inc和lib子目錄添加到默認的頭文件和庫文件搜索路徑中;6U6Linux聯盟

c)在使用MSXML的源文件中包含頭文件<msxml2.h>;6U6Linux聯盟

d)在工程設置中將msxml2.lib添加到要鏈接的庫中。

以自動方式導入MSXML,會在妳的工程目錄下(或者Debug/Release下)生成兩個頭文件msxml4.tlh和msxml4.tli(前者為頭文件聲明,後者為內聯函數定義文件)。

4.2. XML樣例文檔

後面的程序中將動態生成如下XML文檔,然後對該文檔進行查詢。

<?xml version="1.0" encoding="utf-8"?>

<!--Sample XML file created using XML DOM object.-->

<request>

<identification>

<userName>tyc</userName>

<password>pwd</password>

</identification>

<commandLines count="2" reply="no" immediate="yes">

<command num="1">

<type>backup</type>

<dbName>db1359</dbName>

</command>

<command num="2">

<type>save</type>

<data><![CDATA[這裏是XML文檔的CDATA數據段...]]></data>

</command>

</commandLines>

</request>

4.3. 用到的COM技術

與其它COM技術壹樣,MSXML也使用引用計數來管理DOM對象的生存期。當使用MSXML中的COM裸接口指針時,程序員必須負責處理該指針的引用計數:調用AddRef增加引用計數;調用Release減少引用計數。

例如,當調用IXMLDOMDocument::createNode、IXMLDOMNode::appendChild或者 CoCreateInstance創建或者獲取對象時,對象的引用計數已經在函數返回前增加了,而妳卻有責任在使用完這些指針後調用Release釋放對象。如果妳復制壹個已存在對象的引用,妳必須調用AddRef增加相應的引用計數。

4.4. MSXML DOM中裸指針與智能指針的用法區別

MSXML中成員函數有兩類,壹類成員函數的返回值是通過參數返回的,而函數本身返回HRESULT作為操作成功與否的標識,如果函數返回的值(通過參數)是指針,那麽該指針是裸指針,這裏把這類用法稱為裸用法,這種函數稱為裸函數;另壹類成員函數是對前面的裸函數的簡單封裝形式,把裸函數的返回值作為真正的返回值返回,如果是返回指針,則指針不再是裸指針,而是經過封裝的智能指針。壹般前類函數的函數名中有下劃線,而後者沒有。妳可以在生成的 msxml4.tli文件中看到這種封裝。

4.5. 源程序

不多說了,看代碼吧。(註:本來想貼上所有代碼的,但系統字數限制,只好刪除了兩個實現函數,請看文後的源程序打包文件)

#include <iostream>

#include <string>

#include <cassert>

using namespace std;

#import <msxml4.dll>

using namespace MSXML2;

bool generateXMLSampleFile(const string &path);

bool queryXMLSampleFile(const string &path);

int main()

{

// 初始化COM庫

CoInitialize(NULL);

// 創建XML文件及其內容

if (!generateXMLSampleFile("sample.xml"))

cout << "Failed" << endl;

// 加載剛生成的XML文件,將其輸出到標準輸出中予以顯示

IXMLDOMDocument2Ptr pXMLDom;

HRESULT hr = pXMLDom.CreateInstance(__uuidof(DOMDocument40));

if (FAILED(hr)) {

cout << "Failed to instantiate DOMDocument40 class!" << endl;

return -1;

}

if (pXMLDom->load("sample.xml") != VARIANT_TRUE) {

cout << "Failed load xml data from file: " <<

static_cast<char*>(pXMLDom->parseError->Getreason()) << endl;

return -1;

}

// 下面輸出XML文件內容,但奇怪的是文件頭中沒有編碼的部分!

cout << static_cast<char*>(pXMLDom->xml) << endl;

pXMLDom.Release(); // 註意,不能用pXMLDom->Release()這種形式!

// 對剛生成的XML文件進行查詢

cout << "---------------------------------------" << endl;

cout << "Start query..." << endl;

queryXMLSampleFile("sample.xml");

CoUninitialize();

return 0;

}

補充下,如果是遍歷壹個未知XML文檔,就需要使用IXMLDOMDocumentPtr的documentElement獲得根元素,使用 IXMLDOMNodePtr的firstChild、nextSibling成員獲得壹個節點的所有子節點;使用IXMLDOMNodePtr的 nodeType成員來判斷節點類型(元素、屬性、文本,等等),使用text成員得到文本值,使用nodeName成員得到節點名。還可以使用 IXMLDOMDocumentPtr、IXMLDOMNodePtr等的xml成員獲得相應的xml字符串。另詳細的資料請參考MSXML 4.0 SDK文檔。

另外,在程序中動態創建的text節點的text值的數據量大小是有限的,在我的機器上測試發現(默認VC配置),使用256K的數據還正常,但使用512K的數據時就Stack Overflow了。但是,加載XML文檔時是沒有問題的,其數據量並不受此限制。

最後,在妳使用MSXML DOM時,請清醒地認識到它在內部是壹顆樹的表示,任何數據都是以節點形式存在的。That’s all!

  • 上一篇:程序員轉行做大數據是明智的選擇嗎?
  • 下一篇:股票技術分析:什麽是箱體理論?
  • copyright 2024編程學習大全網