MSXML使用教程

DOM接口規範中,有四個基本的接口:DocumentNodeNodeList以及NamedNodeMap。在這四個基本接口中,Document接口是對文檔進行操做的入口,它是從Node接口繼承過來的。Node接口是其餘大多數接口的父類,DocumetElementAttributeTextComment等接口都是從Node接口繼承過來的。NodeList接口是一個節點的集合,它包含了某個節點中的全部子節點。NamedNodeMap接口也是一個節點的集合,經過該接口,能夠創建節點名和節點之間的一一映射關係,從而利用節點名能夠直接訪問特定的節點。下面將對這四個接口分別作一些簡單的介紹。node

 

1Document接口編程

Document接口表明了整個XML/HTML文檔,所以,它是整棵文檔樹的根,提供了對文檔中的數據進行訪問和操做的入口。windows

因爲元素、文本節點、註釋、處理指令等都不能脫離文檔的上下文關係而獨立存在,因此在Document接口提供了建立其餘節點對象的方法,經過該方法建立的節點對象都有一個ownerDocument屬性,用來代表當前節點是由誰所建立的以及節點同Document之間的聯繫。app

DOM樹中,Document節點是DOM樹中的根節點,也即對XML文檔進行操做的入口節點。經過Docuemt節點,能夠訪問到文檔中的其餘節點,如處理指令、註釋、文檔類型以及XML文檔的根元素節點等等。另外,在一棵DOM樹中,Document節點能夠包含多個處理指令、多個註釋做爲其子節點,而文檔類型節點和XML文檔根元素節點都是惟一的。async

關於Document接口的IDLInterface Definition Language接口定義語言)定義和其中一些比較經常使用的屬性和方法的詳細介紹能夠在MSDN中找到。ide

2Node接口函數

Node接口在整個DOM樹中具備舉足輕重的地位,DOM接口中有很大一部分接口是從Node接口繼承過來的,例如,ElementAttrCDATASection等接口,都是從Node繼承過來的。在DOM樹中,Node接口表明了樹中的一個節點。工具

3NodeList接口測試

NodeList接口提供了對節點集合的抽象定義,它並不包含如何實現這個節點集的定義。NodeList用於表示有順序關係的一組節點,好比某個節點的子節點序列。另外,它還出如今一些方法的返回值中,例如GetNodeByNameui

DOM中,NodeList的對象是"live"的,換句話說,對文檔的改變,會直接反映到相關的NodeList對象中。例如,若是經過DOM得到一個NodeList對象,該對象中包含了某個Element節點的全部子節點的集合,那麼,當再經過DOMElement節點進行操做(添加、刪除、改動節點中的子節點)時,這些改變將會自動地反映到NodeList對象中,而不需DOM應用程序再作其餘額外的操做。

NodeList中的每一個item均可以經過一個索引來訪問,該索引值從0開始。

4NamedNodeMap接口

實現了NamedNodeMap接口的對象中包含了能夠經過名字來訪問的一組節點的集合。不過注意,NamedNodeMap並非從NodeList繼承過來的,它所包含的節點集中的節點是無序的。儘管這些節點也能夠經過索引來進行訪問,但這只是提供了枚舉NamedNodeMap中所包含節點的一種簡單方法,並不代表在DOM規範中爲NamedNodeMap中的節點規定了一種排列順序。

NamedNodeMap表示的是一組節點和其惟一名字的一一對應關係,這個接口主要用在屬性節點的表示上。

NodeList相同,在DOM中,NamedNodeMap對象也是"live"的。

 

DOMDocument Object Model(文檔對象模型)的簡稱,是對Web文檔進行應用開發、編程的應用程序接口(API)。做爲W3C公佈的一種跨平臺、與語言無關的接口規範,DOM提供了在不一樣環境和應用中的標準程序接口,能夠用任何語言實現。

DOM採用對象模型和一系列的接口來描述XML文檔的內容和結構,即利用對象把文檔模型化。這種對象模型實現的基本功能包括:

描述文檔表示和操做的接口;

接口的行爲和屬性;

接口之間的關係以及互操做。

DOM可對結構化的XML文檔進行解析,文檔中的指令、元素、實體、屬性等全部內容個體都用對象模型表示,整個文檔被當作是一個有結構的信息樹,而不是簡單的文本流,生成的對象模型就是樹的節點,對象同時包含了方法和屬性。所以,對文檔的全部操做都是在對象樹上的進行。在DOM中,樹中的一切都是對象,不論是根節點仍是實體的屬性。

DOM中主要有如下三個對象:

· XML文檔對象 XML文檔既是一種對象,同時又表明整個XML文檔。它由根元素和子元素組成。

· XML節點對象 XML節點對象表明的是XML文檔內部的節點,如元素、註釋、名字空間等。

· XML節點列表 XML文檔模塊列表表明了節點的集合。

利用DOM,開發人員能夠動態地建立XML文檔,遍歷結構,添加、修改、刪除內容等。其面向對象的特性,令人們在處理XML解析相關的事務時節省大量的精力,是一種符合代碼重用思想的強有力編程工具。

3、MSXML

從理論上說,根據XML的格式定義,咱們能夠本身編寫一個XML的語法分析器,但實際上微軟已經給咱們提供了一個XML語法解析器,即一個叫作MSXML.DLL的動態連接庫,實際上它是一個COMComponent Object Model)對象庫,裏面封裝了進行XML解析時所須要的全部對象。由於COM是一種以二進制格式出現的和語言無關的可重用對象,因此你能夠用任何語言(好比VBVCDELPHIC++ Builder甚至是劇本語言等等)對它進行調用,在你的應用中實現對XML文檔的解析。

MSXML.DLL所包括的主要COM接口有:

1. DOMDocument

DOMDocument對象是XML DOM的基礎,你能夠利用它所暴露的屬性和方法來瀏覽、查詢和修改XML文檔的內容和結構。DOMDocument表示了樹的頂層節點,它實現了DOM文檔的全部的基本方法,而且提供了額外的成員函數來支持XSLXSLT。它建立了一個文檔對象,全部其餘的對象均可以從這個文檔對象中獲得和建立。

2. IXMLDOMNode

IXMLDOMNode是文檔對象模型(DOM)中的基本對象,元素、屬性、註釋、過程指令和其餘的文檔組件均可以認爲是IXMLDOMNode。事實上,DOMDocument對象自己也是一個IXMLDOMNode對象。

3. IXMLDOMNodeList

IXMLDOMNodeList其實是一個節點(Node)對象的集合,節點的增長、刪除和變化均可以在集合中馬上反映出來,能夠經過"for...next"結構來遍歷全部的節點。

4. IXMLDOMParseError

IXMLDOMParseError接口用來返回在解析過程當中所出現的詳細的信息,包括錯誤號、行號、字符位置和文本描述。

使用方法:

在具體應用時能夠用DOMDocumentLoad方法來裝載XML文檔,用IXMLDOMNode selectNodes(查詢的結果有多個,獲得存放搜索結果的鏈表)或selectSingleNode(查詢的結果有一個,在有多個的狀況下返回找到的第一個節點)方法進行查詢,用createNodeappendChild方法來建立節點和追加節點,用IXMLDOMElementsetAttributegetAttribute方法來設置和得到節點的屬性。

4、程序實現

下面經過一個具體的實例來講明在VC++中如何利用MSXML解析XML文檔。

1)源XML文檔(xmlfile.xml)以下:

<?xml version="1.0" encoding="GB2312"?>

<Device id="10041" name="設備1">

<Type>13</Type>

<TypeName>保護</TypeName>

</Device>

咱們在源文檔中查找"Device",將其"name"屬性設置爲"測試設備",爲其添加"Model"節點,並設置其文本爲"3"

2)源程序以下:

CoInitialize(NULL)// 初始化COM

CComPtr<IXMLDOMDocument> spXMLDOM;

// 建立解析器實例。

HRESULT hr = spXMLDOM.CoCreateInstance (_uuidof(DOMDocument));

VARIANT_BOOL bSuccess = false;

// 裝載XML文檔。

Hr = spXMLDOM->load(CComVariant(L"xmlfile.xml"),&bSuccess);

CComBSTR  bstrSS(L"Device");

CComPtr<IXMLDOMNode> spDevice;

Hr = spXMLDOM->selectSingleNode(bstrSS,&spDevice); //搜索"Device"

CComQIPtr<IXMLDOMElement>  spDev;

spDev = spDevice;

// 設置"Device""name"屬性。

Hr = spDev ->setAttribute(CComBSTR(L"name"),CComVariant("測試設備"));

CComPtr<IXMLDOMNode> spModelNode;

// 建立"Model"節點。

Hr = spXMLDOM->createNode(CComVariant(NODE_ELEMENT)ComBSTR

"Model"),NULL,& spModelNode);

CComPtr<IXMLDOMNode> spInsertedNode;

Hr = spDevice->appendChild (spModelNode,&spInsertedNode);

// 添加新節點到"Device"節點下面。

CString strID="3";

// 設置"Model"的文本。

hr=spInsertedNode->put_text(strID.AllocSysString());

/ /保存文檔。

hr=spXMLDOM->save(CComVariant("xmlfile.xml"));

// 結束對COM的使用。

CoUninitialize();

由於篇幅的緣由,上述代碼的每步操做並未對返回的HRESULT類型進行判斷,也未進行異常的捕獲處理,在實際的編程中讀者應根據返回的hr進行決斷,以決定程序的流程,同時應進行異常的捕獲處理。

3修改後的XML文檔以下

<?xml version="1.0" encoding="GB2312"?>

<Device id="10041" name="測試設備">

<Type>13</Type>

<TypeName>保護</TypeName>

<Model>3</Model>

</Device>

MFC程序示例:

 

1、目標文檔:

 <book id="bk101">

      <author>lizlex</author>

      <title>XML Developer's Guide</title>

   </book>

2、步驟:

(1)StdAfx.h中引入動態連接庫 MSXML.DLL(C:\windows\system32\msxml4.dll)

 #import <msxml4.dll>

 

(2)界面設計:

分別放入三個Text,用於輸入數據,與顯示文檔內容用,並添加關聯的成員變量

m_strId, m_strAuthor, m_strTitle;並添加肯定按鈕。

 

(3)產生文檔的程序片段:

void CXmlparseDlg::OnButtonGenerate()

{

 UpdateData();

 MSXML2::IXMLDOMDocumentPtr pDoc;

 MSXML2::IXMLDOMElementPtr xmlRoot ;

 //建立DOMDocument對象

 HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));

 if(!SUCCEEDED(hr))

 { 

 MessageBox("沒法建立DOMDocument對象,請檢查是否安裝了MS XML Parser 運行庫!");

 return ;

 }

 

 //根節點的名稱爲Book

 //建立元素並添加到文檔中

 xmlRoot=pDoc->createElement((_bstr_t)"Book");

 

 //設置屬性

 xmlRoot->setAttribute("id",(const char *)m_strId);

 pDoc->appendChild(xmlRoot);

 MSXML2::IXMLDOMElementPtr pNode;

 //添加「author」元素

 pNode=pDoc->createElement((_bstr_t)"Author");

 pNode->Puttext((_bstr_t)(const char *)m_strAuthor);

 xmlRoot->appendChild(pNode);

 

 //添加「Title」元素

 pNode=pDoc->createElement("Title");

 pNode->Puttext((const char *)m_strTitle);

 xmlRoot->appendChild(pNode);

 

 //保存到文件

 //若是不存在就創建,存在就覆蓋

 pDoc->save("d:\\he.xml");

}

 

(4)讀取XML文檔的程序片段:

void CXmlparseDlg::OnButtonLoad()

{

 MSXML2::IXMLDOMDocumentPtr pDoc;

 HRESULT hr;

 hr=pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));

 if(FAILED(hr))

 { 

 MessageBox("沒法建立DOMDocument對象,請檢查是否安裝了MS XML Parser 運行庫!");

 return ;

 }

 

 //加載文件

 pDoc->load("d:\\he.xml");

 

 MSXML2::IXMLDOMNodePtr pNode;

 

 //在樹中查找名爲Book的節點,"//"表示在任意一層查找

 pNode=pDoc->selectSingleNode("//Book");

 MSXML2::DOMNodeType nodeType;

 

 //獲得節點類型

 pNode->get_nodeType(&nodeType);

 

 //節點名稱

 CString strName;

 

 strName=(char *)pNode->GetnodeName();

 //節點屬性,放在鏈表中

 MSXML2::IXMLDOMNamedNodeMapPtr pAttrMap=NULL;

 MSXML2::IXMLDOMNodePtr   pAttrItem;

 _variant_t variantValue;

 pNode->get_attributes(&pAttrMap);

 

 long count;

 count=pAttrMap->get_length(&count);

 

 pAttrMap->get_item(0,&pAttrItem);

 //取得節點的值

 pAttrItem->get_nodeTypedValue(&variantValue);

 m_strId=(char *)(_bstr_t)variantValue;

 UpdateData(FALSE);

}


在VC中應用MSXML DOM 的一些基本實現方法:     

 已知變量
MSXML2::IXMLDOMDocument *pDoc;
MSXML2::IXMLDOMNode *pChild, *pParent;
MSXML2::IXMLDOMNode *pNod;
MSXML2::IXMLDOMElement *pEle;

 
初始化指針:
MSXML2::IXMLDOMDocument *pDocument=NULL;
MSXML2::IXMLDOMNodeList *pNodeList=NULL;
MSXML2::IXMLDOMNamedNodeMap *pNodeMap=NULL;
MSXML2::IXMLDOMNode *pNode=NULL
MSXML2::IXMLDOMText *pText=NULL;
MSXML2::IXMLDOMElement *pElement=NULL;
MSXML2::IXMLDOMProcessingInstruction *pProcessingInstruction=NULL;
MSXML2::IXMLDOMComment *pComment=NULL;

MSXML2::IXMLDOMParseError *pObjError = NULL;

已知數據:
BSTR bstrText, bstrName;
int  type;

**)建立新文檔
// hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, 
//  IID_IXMLDOMDocument,(void**)&m_pXMLDoc);
HRESULT hr=CoCreateInstance(__uuidof(MSXML2::DOMDocument40),NULL,CLSCTX_INPROC_SERVER,
  __uuidof(MSXML2::IXMLDOMDocument),(void**)&m_pXMLDoc);
    hr = pDocument->put_async(VARIANT_FALSE); 
    hr = pDocument->put_validateOnParse(VARIANT_FALSE);
hr = pDocument->put_resolveExternals(VARIANT_FALSE);
 

a)添加子節點到父節點
pParent->appendChild(pChild, &pNode)
 

b)建立節點
VARIANT vtype;
vtype.vt = VT_I4;
V_I4(&vtype) = (int)type;
pDoc->createNode(vtype, bstrName, NULL, &pNode);

 

c)建立元素節點
pDoc->createElement(bstrName,pElement);
(pElement)->put_text(bstrText);

d)建立文本子節點,並添加到父節點中
pDoc->createTextNode(bstrText,&pText);
pParent->appendChild(pText,& pNode)

 

e)建立// Create a processing instruction element.
BSTR bstrTarget = SysAllocString(L"xml");
BSTR bstrData = SysAllocString(L"version='1.0'");
pDoc ->createProcessingInstruction(bstrTarget, bstrData, &pProcessingInstruction);
SysFreeString(bstrTarget);
SysFreeString(bstrData);

 

f)建立註釋節點
pDoc->createComment(bstrText, &pComment);

 

g)元素節點屬性值
獲得屬性值
VARIANT v;
pEle->getAttribute(bstrName,&v);
CString str = v.bstrVal;
設置屬性值
CComVariant v(str);
pEle->setAttribute(bstrName, v);

 

h)節點屬性值
VARIANT v;
CString str;
long mCount;
獲得節點屬性集
hr=pNod->get_attributes(&pNodeMap);
hr=pNodeMap->get_length(&mCount); 
獲得節點屬性
hr=pNodeMap->getNamedItem(bstrName,&pNode);
pNodeMap->get_item(i,&pNode);
獲得節點屬性值
hr=pNode->get_node
value(&v);
str =v.bstrVal;
刪除節點屬性
MSXML2::IXMLDOMNode *moldNode;
mNodeMape->removeNamedItem(bstrName,&moldNode);
if (moldNode!=NULL) moldNode->Release();

 

i)節點
1)獲得節點、節點集
根據節點名稱
pDoc->getElementsByTagName(bstrName,&pNodeList);
pNodeList->get_item(0,&pNode);
獲得子節點集
hr=pNod->get_childNodes(&mNodeList);
long mCount;
MSXML2::IXMLDOMNode *pNodeSub;
mNodeList->get_length(&mCount);
hr=pNode->get_firstChild(&pNodeSub);
刪除子節點(包含刪除節點屬性、子節點、當前節點)
刪除當前子節點
pNodeList->get_item(i,&pNode);
pNod->removeChild(pNode,&moldNode);
moldNode->Release();

2)根據節點獲得節點名稱
pNod->get_nodeName(&bstrName);
3)根據節點獲得節點值
VARIANT v;
hr=pNod->get_node
value(&v);

 

j)XML文件操做
加載
VARIANT_BOOL status;
VARIANT vFileName;
1
pDoc->loadXML(bstrName,&status);
2
V_BSTR(&vFileName) = strFileName.AllocSysString();
V_VT(&vFileName) = VT_BSTR;
vResult = pDoc->load(vFileName,&status);
保存
BSTR pBFName = mFileName.AllocSysString();
CComVariant v(pBFName);
hr=pDoc->save(v);

BSTR bstr = NULL;
pDoc->get_xml(&bstr);

 

k)錯誤處理 BSTR bstr = NULL; pDoc->get_parseError(&pObjError); pObjError->get_reason(&bstr); AfxMessageBox(_T("Failed to load DOM from books.xml. %S\n"),*bstr);

相關文章
相關標籤/搜索