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。這裡有一個介面繼承關係示意圖:
在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道習題並不是每道題只標記為陣列一個考點,大部分習題都有兩到三個考點。比如,考查陣列+雜湊表、陣列+動態規
(資料科學學習手札104)Python+Dash快速web應用開發——回撥互動篇(上)
> 本文示例程式碼已上傳至我的`Github`倉庫[https://github.com/CNFeffery/DataScienceStudyNotes](https://github.com/CNFeffery/DataScienceStudyNotes) # 1 簡介 這是我的系列教程**Pyt
(資料科學學習手札108)Python+Dash快速web應用開發——靜態部件篇(上)
> 本文示例程式碼已上傳至我的`Github`倉庫[https://github.com/CNFeffery/DataScienceStudyNotes](https://github.com/CNFeffery/DataScienceStudyNotes) # 1 簡介 這是我的系列教程**Pyt
(資料科學學習手札112)Python+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開發MongoDB(2)模型(models)
length 輸出 ror highlight unit required opts nbsp 在一起 數據模型及基礎操作模板 為了使工程結構清晰,將數據模型(Schema, Model)的建立與增刪查改的基礎操作模板寫在一起,命名為數據庫設計中的Collection(
應用Mongoose開發MongoDB(3)控制器(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