1. 程式人生 > >MSXML應用總結 開發篇(上)

MSXML應用總結 開發篇(上)

(由於包含太多格式符號,新浪提示篇幅過長,因此分為上、下兩篇)

    本篇是接前文“MSXML應用總結 概念篇”寫的,主要總結一下MSXML DOM介面的應用。DOM(Document Object Model)是微軟提供的處理XML文件的一個API標準庫,我們可以將其理解為一組抽象了XML文件結構的介面。

    MSXML的DOM模型是符合W3C DOM標準的,而DOM API在Windows中以COM介面的形式提供,關於COM請大家查閱相關資料。簡單來說,COM提供了一個環境和一套規則,使介面的設計實現到物件的建立、使用和釋放都標準化,從而使COM支援跨平臺和跨語言;更重要的是,遵守COM規範使我們程式碼的介面與實現分離,將程式框架的穩定與擴充套件統一起來,對於使用COM介面的人則更加簡單直觀。COM中一個很重要的概念是refcount,即介面物件的訪問計數,通過AddRef和Release兩個介面函式來控制。要想用好refcount還是件較困難的事情,因此我推薦大家使用智慧指標。使用智慧指標就像使用一個簡單指標一樣,我們完全不用去關心指標指向記憶體空間的釋放。

    本篇總結采用API版本是MSXML2.0。

    首先我們看一下常用的介面:

    IXMLDOMDocument:XML文件介面,DOM樹結構的根結點,是對文件訪問和操作的入口;

    IXMLDOMNode:節點介面,該介面是普遍意義上的節點介面,很多型別節點介面都從它派生,包括IXMLDOMDocument;

    IXMLDOMNodeList:節點列表介面,表示一組關聯的節點集合;該列表中的node元素通過index(從0開始)訪問,另外該介面中的元素還是動態的,會隨著XML文件的改變而更新;

    IXMLDOMNamedNodeMap:節點集合介面,也表示一組關聯節點的集合;不過與list不同的是,該集合是無序的,該介面常用於表示節點的屬性集,並且該介面也是動態的;

    IXMLDOMElement:元素介面,一般用來表示一個節點及其屬性;

    IXMLDOMAttribute:節點屬性介面,對節點屬性進行訪問和操作;

    IXMLDOMText:節點中文字控制介面;

    IXMLDOMComment:XML文件中的註釋介面;

    IXMLDOMParseError:出錯處理介面,包括了錯誤的詳細資訊。

    以上都是最常用的DOM介面,還有一些介面沒有在此列出。對於介面來說,都有相應的智慧指標介面,一般為介面名加上Ptr,比如IXMLDOMDocument的智慧指標介面為IXMLDOMDocumentPtr。這裡有一個介面繼承關係示意圖:

PIC

    在VS2005環境下進行DOM應用開發,首先要設定DOM介面應用環境,在stdafx.h檔案中加入語句: 

    #import <msxml3.dll> raw_interfaces_only

    如果你的系統資料夾下有msxml6.dll檔案,#import語句將成生MSXML庫型別資訊,一般會在你的工程編譯資料夾下生成msxml6.tlh和msxml6.tli兩個檔案,開啟看一下可知這兩個檔案包含了一些COM介面型別及函式的宣告以及一些庫資訊。實際上,#import指令使dll庫中的型別資訊匯出為描述的COM介面的c++類標頭檔案。而“raw_interfaces_only”屬性使得生成檔案只有msxml6.tlh一個,而且介面函式只有HRESULT返回型別一種形式,且省去了raw_字首;如果去掉該屬性,則除了在msxml6.tlh檔案中宣告帶raw_字首的返回HRESULT型別的介面函式外,還會在msxml6.tlh中生成不帶raw_字首的wrapper介面函式,並在msxml6.tli檔案中生成返回介面指標型別的wrapper介面函式。因此我們在應用DOM介面的時候,發現有兩套完成相同功能的介面函式,分別返回HRESULT型別和介面指標型別,就是因為上述原因,這應該是Windows環境下COM介面描述的規則,比較深入的介紹請參考這篇文章:http://www.cnblogs.com/xiaotaoliang/archive/2005/07/20/196257.html。為了應用方便,我們下面的示例程式碼不一定用的都是加了“raw_interfaces_only”屬性後的介面函式,建議大家可以去掉該屬性,此處只是加以說明。

    另外一種載入DOM介面的方法是直接在工程環境中新增msxml庫的路徑,並連結msxml6.lib檔案,這裡不再詳述。

    設定DOM環境後,還要初始化COM應用環境,在應用執行緒初始化函式中呼叫CoInitialize,並在執行緒退出時呼叫CoUninitialize。

    現在我們可以用DOM介面來對xml檔案進行操作了,我將按操作分類進行總結。

一、xml檔案的載入和儲存

    由於DOM模型面向的是整個xml檔案,因此我們需要自己建立的介面只有IXMLDOMDocument一個,其他介面都是從它直接或間接得到的,xml檔案的載入和儲存函式也在IXMLDOMDocument介面中實現。建立IXMLDOMDocument介面的程式碼如下:

    MSXML2::IXMLDOMDocumentPtr pXmlDoc;

    HRESULT hr = pXmlDoc.CreateInstance( __uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER);

    if( FAILED(hr))

        printf("Failed to create DOM document interface pointer./n");

    載入xml檔案程式碼為: 

    try

    {

        pXmlDoc->async = VARIANT_FALSE;

        pXmlDoc->validateOnParse = VARIANT_FALSE;

        pXmlDoc->resolveExternals = VARIANT_FALSE;

        if( pXmlDoc->load("test.xml") != VARIANT_TRUE)

{

            printf("Fail reason: %s/n", (LPCSTR)pXmlDoc->parseError->Getreason());

       }

        else

 {

            // success

}

    }

    catch(_com_error errorObject)

    {

        printf("Exception, HRESULT = 0x%08x", errorObject.Error());

    }

    上面程式碼中,開始3句是設定IXMLDOMDocument介面的3個屬性值。

    async表示呼叫的阻塞模式,為true時為非同步,此時load函式呼叫立即返回,而不管檔案載入是否完成;為false時為同步模式,即在載入完之後函式返回。在非同步模式中,可以通過查詢readyState屬性值來判斷是否載入完畢,也可以設定onreadystatechange handler或者onreadystatechange event進行處理。async的預設值為true。

    validateOnParse表示當xml檔案結構有錯誤時是否繼續進行分析,預設值為true。

    resolveExternals表示在分析xml時,外部定義或document type definition(DTD)等是否被處理,MSXML6.0中的預設值為false。

    另外要解釋一下VARIANT型別,一般在COM中用的比較多。VARIANT型別被用來表示多種資料型別,在介面中應用還是很方便的。其實它的定義是一個結構體,其中有一個變數指示了資料的真正型別,還有一個union變數,由各種型別的資料成員構成。這樣,VARIANT就能支援各種型別的資料了。值得一提的是,VARIANT中字串型別是用BSTR表示的,BSTR也是COM程式設計中通用的字串型別,為Unicode字串。BSTR字串的記憶體分配都由系統統一管理,通過SysAllocString和SysFreeString控制。Windows提供了專門的類來處理VARIANT和BSTR,具體可以參考這篇文章:http://www.vckbase.com/document/viewdoc/?id=1096

    load函式既可以載入本地檔案,也可以載入URL形式的遠端檔案(沒有測試)。另外還有一個對應的loadXML函式可以直接載入字串形式的xml,但只支援UTF-16和UCS-2兩種編碼。

    儲存xml檔案的程式碼為:

    try

    {   

          if( FAILED( pXmlDoc->save(L"myData.xml")))

        {

              printf("Fail reason: %s/n", (LPCSTR)pXmlDoc->parseError->Getreason());

          }

          else

          { 

             // success

          }

    }

    catch(_com_error errorObject)

    {

          printf("Exception, HRESULT = 0x%08x", errorObject.Error());

    }

二、獲取root節點指標

    有了IXMLDOMDocument介面指標,就能很方便的得到root節點介面指標。對於載入xml來說,有3種方式,程式碼如下:

    MSXML2::IXMLDOMElementPtr pRootNode = pXmlDoc->documentElement;

    或

    MSXML2::IXMLDOMElementPtr pRootNode;

    pXmlDoc->get_documentElement(&pRootNode);

    或

    MSXML2::IXMLDOMNodePtr pRootNode, pNode;

    pXmlDoc->get_firstChild(&pRootNode);

    while( pRootNode)

    {

         MSXML2::DOMNodeType type;

         pRootNode->get_nodeType(&type);

         if(type==NODE_ELEMENT)

              break;

         pNode = pRootNode;

         pNode->get_nextSibling(&pRootNode);

    }  

    最常用的又簡單的方法就是第一種。寫出後兩種方法是想說明兩個問題,後面的操作方法將只介紹最常用的方法。

    可以看到第二種方法並不是直接訪問的IXMLDOMDocument介面的屬性值,而是通過函式得到。對於DOM介面的屬性,一般都有對應的get或put函式來對屬性進行讀寫。

    第三種方法是為了讓大家再次理解各種型別的node之間的聯絡與區別,我們可以看到IXMLDOMDocument和IXMLDOMElement均為一個IXMLDOMNode,我們可以通過遍歷IXMLDOMDocument的子節點得到root節點。只不過要注意的是,IXMLDOMDocument的get_firstChild返回的節點並不一定就是root,可能是一些註釋或空格行之類,我們需要判斷節點型別。節點型別的種類及說明如下表:

種類

意義

子節點型別

父節點型別

NODE_ELEMENT

1

表示一個元素

ProcessingInstruction, Text, Comment, CDATASection, EntityReference, Element

Document, DocumentFragment, EntityReference, Element

NODE_ATTRIBUTE

2

表示元素的屬性

Text ,  EntityReference

NODE_TEXT

3

表示一個標籤的文字

Attribute, DocumentFragment, Element, EntityReference

NODE_CDATA_SECTION

4

表示一個CDATA section

DocumentFragment, EntityReference, Element

NODE_ENTITY_REFERENCE

5

表示實體引用

Element, Text, ProcessingInstruction, Comment, CDATASection, EntityReference

Attribute, DocumentFragment, Element, EntityReference

NODE_ENTITY

6

表示擴充套件實體

可表示該實體的節點型別

DocumentType

NODE_PROCESSING_INSTRUCTION

7

表示一個操作指示

Document, DocumentFragment, Element, EntityReference

NODE_COMMENT

8

表示註釋

Document, DocumentFragment, Element, EntityReference

NODE_DOCUMENT

9

表示xml文件

Element, ProcessingInstruction, Comment,  DocumentType

NODE_DOCUMENT_TYPE

10

表示文件型別宣告,出現在<!DOCTYPE>標籤中

Notation,  Entity

Document

NODE_DOCUMENT_FRAGMENT

11

表示文件片段或與文件

Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference

NODE_NOTATION

12

表示DTD中宣告的表示法

Document

    而對於新建的一個xml來說,我們建立IXMLDOMDocument介面後,呼叫createElement_x函式建立的第一個節點即為root節點。

原文:http://blog.sina.com.cn/s/blog_48f93b530100ejv9.html

相關推薦

MSXML應用總結 開發

(由於包含太多格式符號,新浪提示篇幅過長,因此分為上、下兩篇)     本篇是接前文“MSXML應用總結 概念篇”寫的,主要總結一下MSXML DOM介面的應用。DOM(Document Object Model)是微軟提供的處理XML文件的一個API標準庫,我們可以將其理

LeetCode刷題總結-陣列

       陣列是演算法中最常用的一種資料結構,也是面試中最常考的考點。在LeetCode題庫中,標記為陣列型別的習題到目前為止,已累計到了202題。然而,這202道習題並不是每道題只標記為陣列一個考點,大部分習題都有兩到三個考點。比如,考查陣列+雜湊表、陣列+動態規

資料科學學習手札104Python+Dash快速web應用開發——回撥互動

> 本文示例程式碼已上傳至我的`Github`倉庫[https://github.com/CNFeffery/DataScienceStudyNotes](https://github.com/CNFeffery/DataScienceStudyNotes) # 1 簡介    這是我的系列教程**Pyt

資料科學學習手札108Python+Dash快速web應用開發——靜態部件

> 本文示例程式碼已上傳至我的`Github`倉庫[https://github.com/CNFeffery/DataScienceStudyNotes](https://github.com/CNFeffery/DataScienceStudyNotes) # 1 簡介    這是我的系列教程**Pyt

資料科學學習手札112Python+Dash快速web應用開發——表單控制元件

> 本文示例程式碼已上傳至我的`Github`倉庫[https://github.com/CNFeffery/DataScienceStudyNotes](https://github.com/CNFeffery/DataScienceStudyNotes) # 1 簡介    這是我的系列教程**Pyt

使用MyEclipse開發Java EE應用:EJB項目開發初探

編輯器 應用服務器 工具 xdoclet 屬性 ctu xdoc 直接 project 你開學,我放價!MyEclipse線上狂歡繼續!火熱開啟中>> 【MyEclipse最新版下載】 一、MyEclipse EJB開發工具 Enterprise Java

短視頻app源碼開發經驗分享——功能機制

簡單 人工 轉化 2018年 完整 推薦 shadow 識別 後臺 繼直播平臺爆紅之後,短視頻APP也在2018年“重獲新生”,在快手短視頻低調運營的同時,今日頭條旗下的抖音APP,西瓜視頻等持續發力,目前抖音短視頻已成為國內“超好玩的短視頻APP”,隨後騰訊也布局短視頻市

打造一個企業級應用的微服務開發框架---從服務註冊中心到服務管理中心

【摘要】近年來越來越多的企業開始實踐微服務,本文分為上下兩篇介紹微服務框架ServiceComb如何幫助企業應用進行微服務化,實現快速交付,並可靠地執行在雲端。上篇介紹ServiceComb的服務管理中心設計。近年來越來越多的企業開始實踐微服務,而微服務在企業應用落地的過程,面臨著微服務開發框架的選型,無論是

程式設計師開發學習利器之百度搜索-你真的會用百度嗎

以下內容,開發初學者看,熟手略過。 論語有言: 工欲善其事 必先利其器 ,意思是工匠想要使他的工作做好,一定要先讓工具鋒利。比喻要做好一件事,準備工作非常重要。 這對於我們程式設計師做開發時也是這樣,充足且好的準備工作,不但可以提高我們的開發效率,同時也可以讓我們事半功倍

WEB開發7 Hibernate

  Hibernate是資料持久化的一種解決方案。 介紹ORM 認識Hibernate H

Django中級

[0 新頁面 cor except setup png int ros action Form驗證 django中的Form一般有兩種功能: 輸入html-----------不能你自己寫一些標簽,而幫你自動生成 驗證用戶輸入-------將用戶驗證信息保存起來,可以傳到

應用Mongoose開發MongoDB2模型models

length 輸出 ror highlight unit required opts nbsp 在一起 數據模型及基礎操作模板 為了使工程結構清晰,將數據模型(Schema, Model)的建立與增刪查改的基礎操作模板寫在一起,命名為數據庫設計中的Collection(

應用Mongoose開發MongoDB3控制器controllers

條目 選擇 mongoose 電腦 java 組合 將在 light sta 控制器的基本構成與如何通過路由調用 控制器中通過建立函數並導出,實現前端對數據庫的查詢、新建、刪除與修改的需求,並使之可以在路由中調用,完成API的封裝。本文著重於結構之間的關系,具體問題解決

Oracle JET 單頁面應用程序Router 使用

模塊名 self. put pla function border routing 都是 功能   單頁面應用程序:使用一個進加載一次的網頁,如果頁面由於用戶的交互而改變,則僅繪制更改的頁面部分。   要創建單頁面應用程序需要使用 oj.Router 的虛擬導航來支持,oj

LLDB使用

integer 無法 輸入 信息 debug jpg doc img 分享圖片 LLDB是個開源的內置於XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安裝C++或者Python插件。 本系列針對於已經知道何為debugge

Exchange 2016部署實施案例-01.架構設計

架構設計 Ex架構設計 Exchange架構設計 Exchange 2016架構設計 Exchange架構規劃 年前就答應大家要給大家寫一個關於Exchange規劃部署的文章,一直忙到現在也沒有倒出時間來寫這個東西。特別是節後,更是開工不利啊,各種奇葩問題,真心無語了。廢話就不多說了,開始

Exchange 2016部署實施案例-03.Exchange部署

Exchange部署 Exchange 2016 Exchange先決條件 Exchange 2016先決條件 Exchange 2016部署 距離上一篇《Exchange 2016部署實施案例篇-02.活動目錄部署篇》博文更新已經過去快一周了,最近一直在忙項目上的事情和軟考,整的真心有點

Exchange 2016部署實施案例-04.Ex基礎配置

Exchange安裝 Exchange初始化配置 Exchange 證書配置 證書服務器安裝 CA服務器配置 我們在上一篇中完成了Exchange Server 2016 CU8的安裝《Exchange 2016部署實施案例篇-03.Exchange部署篇(下)》,接下來我們將進入配置相關

APICloud知識教程 | sendEvent、execScript的應用附源碼

。。 app hide dem true html href 可選 format 給大家分享一個小demo,關於sendEvent和execScript的使用,由於內容過多,本期內容將分為上、下兩篇為大家奉上。sendEvent和execScript 這兩個API個人覺得還

機器學習實戰教程:線性回歸基礎

學習 reg style spa 目標 pub auto 機器 輸入 一 什麽是回歸?   回歸的目的是預測數值型的目標值,最直接的辦法是依據輸入,寫入一個目標值的計算公式。   假如你想預測小姐姐男友汽車的功率,可能會這麽計算:               Ho