利用MSXML解析XML文本
當(dāng)前Web上流行的劇本語言是以HTML為主的語言結(jié)構(gòu),HTML是一種標(biāo)記語言,而不是一種編程語言,主要的標(biāo)記是針對顯示,而不是針對文檔內(nèi)容本身結(jié)構(gòu)的描述的。也就是說,機(jī)器本身是不能夠解析它的內(nèi)容的,所以就出現(xiàn)了XML語言。XML (eXtensible Markup Language)語言是SGML語言的子集,它保留了SGML主要的使用功能,同時大大縮減了SGML的復(fù)雜性。XML語言系統(tǒng)建立的目的就是使它不僅能夠表示文檔的內(nèi)容,而且可以表示文檔的結(jié)構(gòu),這樣在同時能夠被人類理解的同時,也能夠被機(jī)器所理解。XML要求遵循一定的嚴(yán)格的標(biāo)準(zhǔn)。XML分析程序比HTML瀏覽器更加要挑剔語法和結(jié)構(gòu),XML要求正在創(chuàng)建的網(wǎng)頁正確的使用語法和結(jié)構(gòu),而不是象HTML一樣,通過瀏覽器推測文檔中應(yīng)該是什么東西來實(shí)現(xiàn)HTML的顯示,XML使得分析程序不論在性能還是穩(wěn)定性方面都更容易實(shí)現(xiàn)。XML文檔每次的分析結(jié)果都是一致的,不象HTML,不同的瀏覽器可能對同一個HTML作出不同的分析和顯示。同時因?yàn)榉治龀绦虿恍枰〞r間重建不完整的文檔,所以它們能比同類HTML能更有效地執(zhí)行其任務(wù)。它們能全力以赴地根據(jù)已經(jīng)包含在文檔中的那個樹結(jié)構(gòu)建造出相應(yīng)的樹來,而不用在信息流中的混合結(jié)構(gòu)的基礎(chǔ)上進(jìn)行顯示。XML標(biāo)準(zhǔn)是對數(shù)據(jù)的處理應(yīng)用,而不是只針對Web網(wǎng)頁的。任何類型的應(yīng)用都可以在分析程序的上面進(jìn)行建造,瀏覽器只是XML的一個小的組成部分。當(dāng)然,瀏覽仍舊極其重要,因?yàn)樗鼮閄ML工作人員提供用于閱讀信息的友好工具。但對更大的項(xiàng)目來說它就不過是一個顯示窗口。因?yàn)閄ML具有嚴(yán)格的語法結(jié)構(gòu),所以我們甚至可以用XML來定義一個應(yīng)用層的通訊協(xié)議,比如互聯(lián)網(wǎng)開放貿(mào)易協(xié)議(Internet Open Trading Protocol)就是用XML來定義的。從某種意義上說,以前我們用BNF范式定義的一些協(xié)議和格式從原則上說都可以用XML來定義。實(shí)際上,如果我們有足夠的耐心,我們完全可以用XML來定義一個C++語言的規(guī)范。
當(dāng)然,XML允許大量HTML樣式的形式自由的開發(fā),但是它對規(guī)則的要求更加嚴(yán)格。 XML主要有三個要素:DTD(Document Type Declaration——文檔類型聲明)或XML Schema(XML大綱)、XSL(eXtensible Stylesheet Language——可擴(kuò)展樣式語言)和XLink(eXtensible Link Language——可擴(kuò)展鏈接語言)。DTD和XML大綱規(guī)定了XML文件的邏輯結(jié)構(gòu),定義了XML文件中的元素、元素的屬性以及元素和元素的屬性之間的關(guān)系;Namespace(名域)實(shí)現(xiàn)統(tǒng)一的XML文檔數(shù)據(jù)表示以及數(shù)據(jù)的相互集成;XSL是用于規(guī)定XML文檔呈現(xiàn)樣式的語言,它使得數(shù)據(jù)與其表現(xiàn)形式相互獨(dú)立,比如XSL能使Web瀏覽器改變文檔的表示法,例如數(shù)據(jù)的顯示順序的變化,不需要再與服務(wù)器進(jìn)行通訊。通過改變樣式表,同一個文檔可以顯示得更大,或者經(jīng)過折疊只顯示外面得一層,或者可以變?yōu)榇蛴〉酶袷?。而XLink 將進(jìn)一步擴(kuò)展目前Web上已有的簡單鏈接。
XML文檔對象(XML DOM)模型分析
XML DOM 對象提供了一個標(biāo)準(zhǔn)的方法來操作存儲在XML文檔中的信息,DOM應(yīng)用編程接口(API)用來作為應(yīng)用程序和XML文檔之間的橋梁。
DOM可以認(rèn)為是一個標(biāo)準(zhǔn)的結(jié)構(gòu)體系用來連接文檔和應(yīng)用程序(也可以是劇本語言)。MSXML解析器允許你裝載和創(chuàng)建一個文檔,收集文檔的錯誤信息,得到和操作文檔中的所有的信息和結(jié)構(gòu),并把文檔保存在一個XML文件中。DOM提供給用戶一個接口來裝載、到達(dá)和操作并序列化XML文檔。DOM提供了對存儲在內(nèi)存中的XML文檔的一個完全的表示,提供了可以隨機(jī)訪問整個文檔的方法。DOM允許應(yīng)用程序根據(jù)MSXML解析器提供的邏輯結(jié)構(gòu)來操作XML文檔中的信息。利用MSXML所提供的接口來操作XML。
實(shí)際上MSXML解析器根據(jù)XML文檔生成一個DOM樹結(jié)構(gòu),它能夠讀XML文檔并根據(jù)XML文檔內(nèi)容創(chuàng)建一個節(jié)點(diǎn)的邏輯結(jié)構(gòu),文檔本身被認(rèn)為是一個包含了所有其他節(jié)點(diǎn)的節(jié)點(diǎn)。
DOM使用戶能夠把文檔看成是一個有結(jié)構(gòu)的信息樹,而不是簡單的文本流。這樣應(yīng)用程序或者是劇本即使不知道XML的語義細(xì)節(jié)也能夠方便的操作該結(jié)構(gòu)。DOM包含兩個關(guān)鍵的抽象:一個樹狀的層次、另一個是用來表示文檔內(nèi)容和結(jié)構(gòu)的節(jié)點(diǎn)集合。樹狀層次包括了所有這些節(jié)點(diǎn),節(jié)點(diǎn)本身也可以包含其他的節(jié)點(diǎn)。這樣的好處是對于開發(fā)人員來說,他可以通過這個層次結(jié)構(gòu)來找到并修改相應(yīng)的某一個節(jié)點(diǎn)的信息。DOM把節(jié)點(diǎn)看成是一個通常的對象,這樣就有可能創(chuàng)建一個劇本來裝載一個文檔,然后遍歷所有的節(jié)點(diǎn),顯示感興趣的節(jié)點(diǎn)的信息。注意節(jié)點(diǎn)可以有很多中具體的類型,比如元素、屬性和文本都可以認(rèn)為是一個節(jié)點(diǎn)。
微軟的MSXML解析器讀一個XML文檔,然后把它的內(nèi)容解析到一個抽象的信息容器中稱為節(jié)點(diǎn)(NODES)。這些節(jié)點(diǎn)代表文檔的結(jié)構(gòu)和內(nèi)容,并允許應(yīng)用程序來讀和操作文檔中的信息而不需要顯示的知道XML的語義。在一個文檔被解析以后,它的節(jié)點(diǎn)能夠在任何時候被瀏覽而不需要保持一定的順序。
通過DOM對XML文檔進(jìn)行解析的圖例如圖1所示。
圖1
對開發(fā)人員來說,最重要的編程對象是DOMDocument。DOMDocument對象通過暴露屬性和方法來允許你瀏覽,查詢和修改XML文檔的內(nèi)容和結(jié)構(gòu),每一個接下來的對象暴露自己的屬性和方法,這樣你就能夠收集關(guān)于對象實(shí)例的信息,操作對象的值和結(jié)構(gòu),并導(dǎo)航到樹的其他對象上去。
MSXML.DLL所包括的主要的COM接口有:
(1)DOMDocument
DOMDocument對象是XML DOM的基礎(chǔ),你可以利用它所暴露的屬性和方法來允許你瀏覽、查詢和修改XML文檔的內(nèi)容和結(jié)構(gòu)。DOMDocument表示了樹的頂層節(jié)點(diǎn)。它實(shí)現(xiàn)了DOM文檔的所有的基本的方法并且提供了額外的成員函數(shù)來支持XSL和XSLT。它創(chuàng)建了一個文檔對象,所有其他的對象都可以從這個文檔對象中得到和創(chuàng)建。
(2)IXMLDOMNode
IXMLDOMNode是文檔對象模型(DOM)中的基本的對象,元素,屬性,注釋,過程指令和其他的文檔組件都可以認(rèn)為是IXMLDOMNode,事實(shí)上,DOMDocument對象本身也是一個IXMLDOMNode對象。
(3)IXMLDOMNodeList
IXMLDOMNodeList實(shí)際上是一個節(jié)點(diǎn)(Node)對象的集合,節(jié)點(diǎn)的增加、刪除和變化都可以在集合中立刻反映出來,可以通過"for...next"結(jié)構(gòu)來遍歷所有的節(jié)點(diǎn)。
(4)IXMLDOMParseError
IXMLDOMParseError接口用來返回在解析過程中所出現(xiàn)的詳細(xì)的信息,包括錯誤號,行號,字符位置和文本描述。
下面主要描述一個DOMDocument對象的創(chuàng)建過程,這里我們用VC描述創(chuàng)建一個文檔對象的過程。
HRESULT hr;
IXMLDomDocument* pXMLDoc;
IXMLDOMNode* pXDN;
Hr=CoInitialize(NULL); //COM的初始化
//得到關(guān)于IXMLDOMDocument接口的指針pXMLDOC。
hr=CoCreateInstance(CLSID_DOMDocument,NULL,CLSCTX_INPPROC_SERVER,
IID_IXMLDOMDocument,(void**)&pXMLDoc);
//得到關(guān)于IXMLDOMNode接口的指針pXDN。
hr=pXMLDoc->QueryInterface(IID_IXMLDOMNode,(void**)&pXDN);
在MSXML解析器使用過程中,我們可以使用文檔中的createElement方法來創(chuàng)建一個節(jié)點(diǎn)裝載和保存XML文件。通過load或者是loadXML方法可以從一個指定的URL來裝載一個XML文檔。Load(LoadXML)方法帶有兩個參數(shù):第一個參數(shù)xmlSource表示需要被解析的文檔,第二個參數(shù)isSuccessful表示文檔裝載是否成功。Save方法是用來把文檔保存到一個指定的位置。Save方法有一個參數(shù)destination用來表示需要保存的對象的類型,對象可以是一個文件,一個ASP Response方法,一個XML文檔對象,或者是一個能夠支持持久保存(persistence)的客戶對象。下面是save方法使用的一個簡單的例子(具體程序請參見http://www.swm.com.cn/swm/200101/利用MSXML解析XML文本)。
同時,在解析過程中,我們需要得到和設(shè)置解析標(biāo)志。利用不同的解析標(biāo)志,我們可能以不同的方法來解析一個XML文檔。XML標(biāo)準(zhǔn)允許解析器驗(yàn)證或者不驗(yàn)證文檔,允許不驗(yàn)證文檔的解析過程跳過對外部資源的提取。另外,你可能設(shè)置標(biāo)志來表明你是否要從文檔中移去多余的空格。
為了達(dá)到這個目的,DOMDocument對象暴露了下面幾個屬性,允許用戶在運(yùn)行的時候改變解析器的行為:
(1)Async(相對于C++是兩個方法,分別為get_async和put_async)
(2)ValidateOnparse (相對于C++是兩個方法,分別為get_validateOnParse和 put_validateOnParse)
(3)ResolveExternals(相對于C++是兩個方法,分別為get_ ResolveExternals和put_ ResolveExternals)
(4)PersercveWhiteSpace(相對于C++是兩個方法,分別為get_ PersercveWhiteSpace和put_ PersercveWhiteSpace)
每一個屬性可以接受或者返回一個Boolean值。缺省的,anync,validateOnParse,resolveExternals的值為TRUE,perserveWhiteSpace的值跟XML文檔的設(shè)置有關(guān),如果XML文檔中設(shè)置了xml:space屬性的話,該值為FALSE。
同時在文檔解析過程中可以收集一些和文檔信息的信息,實(shí)際上在文檔解析過程中可以得到以下的信息:
(1)doctype(文檔類型):實(shí)際上是和用來定義文檔格式的DTD文件。如果XML文檔沒有相關(guān)的DTD文檔的話,它就返回NULL。
(2)implementation(實(shí)現(xiàn)):表示該文檔的實(shí)現(xiàn),實(shí)際上就是用來指出當(dāng)前文檔所支持的XML的版本。
(3)parseError(解析錯誤):在解析過程中最后所發(fā)生的錯誤。
(4)readyState(狀態(tài)信息):表示XML文檔的狀態(tài)信息,readyState對于異步使用微軟的XML解析器來說的重要作用是提高了性能,當(dāng)異步裝載XML文檔的時候,你的程序可能需要檢查解析的狀態(tài),MSXML提供了四個狀態(tài),分別為正在狀態(tài),已經(jīng)狀態(tài),正在解析和解析完成。
(5)url(統(tǒng)一資源定位):關(guān)于正在被裝載和解析的XML文檔的URL的情況。注意如果該文檔是在內(nèi)存中建立的話,這個屬性返回NULL值。
在得到文檔樹結(jié)構(gòu)以后,我們可以操作樹中的每一個節(jié)點(diǎn),可以通過兩個方法得到樹中的節(jié)點(diǎn),分別為nodeFromID和getElementsByTagName。
nodeFromID包括兩個參數(shù),第一個參數(shù)idString用來表示ID值,第二個參數(shù)node返回指向和該ID相匹配的NODE節(jié)點(diǎn)的接口指針。注意根據(jù)XML的技術(shù)規(guī)定,每一個XML文檔中的ID值必須是唯一的而且一個元素(element)僅且只能和一個ID相關(guān)聯(lián)。
getElementsByTagName方法有兩個參數(shù),第一個參數(shù)tagName表示需要查找的元素(Element)的名稱,如果tagName為"*"的話返回文檔中所有的元素(Element)。第二個參數(shù)為resultList,它實(shí)際是指向接口IXMLDOMNodeList的指針,用來返回和tagName(標(biāo)簽名字)相關(guān)的所有的Node的集合。
下面是一個簡單的例子
下面是save方法使用的一個簡單的例子:
BOOL DOMDocSaveLocation() { BOOL bResult = FALSE; IXMLDOMDocument *pIXMLDOMDocument = NULL; HRESULT hr; try { _variant_t varString = _T("D:\\sample.xml"); // 這里需要創(chuàng)建一個DOMDocument對象和裝載XML文檔,代碼省略. hr = pIXMLDOMDocument->save(varString); //保存文檔到D:\\sample.xml中去。 if(SUCCEEDED(hr)) bResult = TRUE; } catch(...) { DisplayErrorToUser(); // 這里需要釋放對IXMLDOMDocument接口的引用,代碼省略。 } return bResult; }
例子2
IXMLDOMDocument *pIXMLDOMDocument = NULL;
wstring strFindText (_T("author"));
IXMLDOMNodeList *pIDOMNodeList = NULL;
IXMLDOMNode *pIDOMNode = NULL;
long value; BSTR bstrItemText;
HRESULT hr;
try { // 創(chuàng)建一個DOMDocument文檔對象,并裝載具體文檔,相關(guān)代碼省略。
//下面的代碼用來得到一個和標(biāo)簽名稱author相關(guān)的所有的節(jié)點(diǎn)集合
hr = pIXMLDOMDocument->getElementsByTagName( (TCHAR*)strFindText.data(), &pIDOMNodeList);
SUCCEEDED(hr) ? 0 : throw hr; //是否正確的得到了指向IDOMNodeList的指針。
hr = pIDOMNodeList->get_length(&value); //得到所包含的NODE節(jié)點(diǎn)的個數(shù)
if(SUCCEEDED(hr)) { pIDOMNodeList->reset(); for(int ii = 0; ii < value; ii++) { //得到具體的一個NODE節(jié)點(diǎn)
pIDOMNodeList->get_item(ii, &pIDOMNode);
if(pIDOMNode ) { pIDOMNode->get_text(&bstrItemText); //得到該節(jié)點(diǎn)相關(guān)的文本信息
::MessageBox(NULL, bstrItemText,strFindText.data(), MB_OK);
pIDOMNode->Release(); pIDOMNode = NULL; }
}
}
pIDOMNodeList->Release(); pIDOMNodeList = NULL;
}
catch(...)
{ if(pIDOMNodeList) pIDOMNodeList->Release();
if(pIDOMNode) pIDOMNode->Release();
DisplayErrorToUser();
}
簡單的實(shí)例程序
#include //下面的.h文件是在安裝了最新的XML Parser以后所包含的.h文件。
#include "C:\Program Files\Microsoft XML Parser SDK\inc\msxml2.h"
#include void main()
{ // 初始化COM接口
CoInitialize(NULL); //在程序中,我們假定我們裝載的XML文件名稱為xmldata.xml,它缺省的和可執(zhí)行文
//件在同一個目錄中。該文件的內(nèi)容如下:
// // // // Hello, World! // //
//程序?qū)ふ颐麨?xmlnode"的節(jié)點(diǎn),然后插入一個新的名稱為"xmlchildnode"的
//節(jié)點(diǎn),然后它去尋找一個名為"xmltest"的節(jié)點(diǎn),然后提取包含在節(jié)點(diǎn)中的文本并顯
//示它。最后它把新的改變過的XML文檔保存在名稱為"updatexml.xml"的文檔中。
try { // 通過智能指針創(chuàng)建一個解析器的實(shí)例。
CComPtr spXMLDOM;
HRESULT hr = spXMLDOM.CoCreateInstance(__uuidof(DOMDocument));
if ( FAILED(hr) ) throw "不能創(chuàng)建XML Parser對象";
if ( spXMLDOM.p == NULL ) throw "不能創(chuàng)建XML Parser對象";
// 如果對象創(chuàng)建成功的話,就開始裝載XML文檔 VARIANT_BOOL bSuccess = false;
hr = spXMLDOM->load(CComVariant(L"xmldata.xml"),&bSuccess);
if ( FAILED(hr) ) throw "不能夠在解析器中裝載XML文檔";
if ( !bSuccess ) throw "不能夠在解析器中裝載XML文檔";
// 檢查并搜索"xmldata/xmlnode" CComBSTR bstrSS(L"xmldata/xmlnode");
CComPtr spXMLNode;
//用接口IXMLDOMDocument的方法selectSingleNode方法定位該節(jié)點(diǎn)
hr = spXMLDOM->selectSingleNode(bstrSS,&spXMLNode);
if ( FAILED(hr) ) throw "不能在XML節(jié)點(diǎn)中定位‘xmlnode‘ ";
if ( spXMLNode.p == NULL ) throw "不能在XML節(jié)點(diǎn)中定位‘xmlnode‘ ";
//DOM對象"spXMLNode"現(xiàn)在包含了XML節(jié)點(diǎn),所以我們可以在
//它下面創(chuàng)建一個子節(jié)點(diǎn)并把找到的該節(jié)點(diǎn)作為它的父節(jié)點(diǎn)。
CComPtr spXMLChildNode; //用接口IXMLDOMDocument的方法createNode方法創(chuàng)建一個新節(jié)點(diǎn)。
hr = spXMLDOM->createNode( CComVariant(NODE_ELEMENT), CComBSTR("xmlchildnode"), NULL,&spXMLChildNode);
if ( FAILED(hr) ) throw "不能創(chuàng)建‘xmlchildnode‘ 節(jié)點(diǎn)";
if ( spXMLChildNode.p == NULL ) throw "不能創(chuàng)建‘xmlchildnode‘ 節(jié)點(diǎn)";
//添加新節(jié)點(diǎn)到spXMLNode節(jié)點(diǎn)下去。
CComPtr spInsertedNode;
hr = spXMLNode->appendChild(spXMLChildNode,&spInsertedNode);
if ( FAILED(hr) ) throw "不能創(chuàng)建‘xmlchildnode‘ 節(jié)點(diǎn)";
if ( spInsertedNode.p == NULL ) throw "不能移動‘xmlchildnode‘ 節(jié)點(diǎn)"; //對新節(jié)點(diǎn)添加屬性。
CComQIPtr spXMLChildElement;
spXMLChildElement = spInsertedNode;
if ( spXMLChildElement.p == NULL ) throw "不能在XML元素接口中查詢到‘xmlchildnode‘ ";
//設(shè)置新節(jié)點(diǎn)的屬性
hr = spXMLChildElement->setAttribute(CComBSTR(L"xml"),CComVariant(L"fun"));
if ( FAILED(hr) ) throw "不能插入新的屬性"; //下面的程序段用來尋找一個節(jié)點(diǎn)并顯示該節(jié)點(diǎn)的相關(guān)信息
// 查找"xmldata/xmltext"節(jié)點(diǎn)
spXMLNode = NULL; // 釋放先前的節(jié)點(diǎn)
bstrSS = L"xmldata/xmltext";
hr = spXMLDOM->selectSingleNode(bstrSS,&spXMLNode);
if ( FAILED(hr) ) throw "不能定位‘xmltext‘節(jié)點(diǎn)";
if ( spXMLNode.p == NULL ) throw "不能定位‘xmltext‘節(jié)點(diǎn)"; // 得到該節(jié)點(diǎn)包含的文本并顯示它
CComVariant varValue(VT_EMPTY);
hr = spXMLNode->get_nodeTypedValue(&varValue);
if ( FAILED(hr) ) throw "不能提取‘xmltext‘文本";
if ( varValue.vt == VT_BSTR )
{ // 顯示結(jié)果,注意這里要把字符串從形式BSTR轉(zhuǎn)化為ANSI USES_CONVERSION;
LPTSTR lpstrMsg = W2T(varValue.bstrVal);
std::cout << lpstrMsg << std::endl; } // if else { // 如果出現(xiàn)錯誤 throw "不能提取‘xmltext‘文本"; }
// else //保存修改過的XML文檔到指定的文檔名
hr = spXMLDOM->save(CComVariant("updatedxml.xml"));
if ( FAILED(hr) ) throw "不能保存修改過的XML文檔";
std::cout << "處理完成..." << std::endl << std::endl; }
// try catch(char* lpstrErr) { // 出現(xiàn)錯誤
std::cout << lpstrErr << std::endl << std::endl; }
// catch catch(...) { // 未知錯誤
std::cout << "未知錯誤..." << std::endl << std::endl; }
// catch // 結(jié)束對COM的使用
CoUninitialize();
}
最后我們討論一下如何來創(chuàng)建新的節(jié)點(diǎn),實(shí)際上可以通過方法createNode來創(chuàng)建一個新的節(jié)點(diǎn)。CreateNode包括四個參數(shù),第一個參數(shù)Type表示要創(chuàng)建的節(jié)點(diǎn)的類型,第二個參數(shù)name表示新節(jié)點(diǎn)的nodeName的值,第三個參數(shù)namespaceURI表示該節(jié)點(diǎn)相關(guān)的名字空間,第四個參數(shù)node表示新創(chuàng)建的節(jié)點(diǎn)。注意可以通過使用已經(jīng)提供的類型(Type),名稱(name)和名字空間(nodeName)來創(chuàng)建一個節(jié)點(diǎn)。
當(dāng)一個節(jié)點(diǎn)被創(chuàng)建的時候,它實(shí)際上是在一個名字空間范圍(如果已經(jīng)提供了名字空間的話)內(nèi)創(chuàng)建的。如果沒有提供名字空間的話,它實(shí)際上是在文檔的名字空間范圍內(nèi)創(chuàng)建的。
利用MSXML進(jìn)行XML文檔分析的簡單實(shí)例為了說明如何在VC中使用XML DOM模型,這里我們顯示了一個簡單的實(shí)例程序(具體程序請參見http://www.swm.com.cn/swm/200101/利用MSXML解析XML文本),是一個Console Application。下面是主要的程序代碼,本代碼用來在一個XML文檔中定位一個特殊的Node節(jié)點(diǎn),并插入一個新的子節(jié)點(diǎn)。
為了說明如何在VC中使用XML DOM模型,這里我們顯示了一個簡單的實(shí)例程序(具體程序請參見http://www.swm.com.cn/swm/200101/利用MSXML解析XML文本),是一個Console Application。下面是主要的程序代碼,本代碼用來在一個XML文檔中定位一個特殊的Node節(jié)點(diǎn),并插入一個新的子節(jié)點(diǎn)。總結(jié)
XML文檔因?yàn)橛兄菻TML嚴(yán)格的多的語法要求,所以使用和編寫一個XML解析器要比編寫一個HTML的解析器要容易的多。同時因?yàn)閄ML文檔不僅可以標(biāo)記文檔的顯示屬性,更重要的是它標(biāo)記了文檔的結(jié)構(gòu)和包含信息的特征,所以我們可以方便的通過XML解析器來獲取特定節(jié)點(diǎn)的信息并加以顯示或修改,方便了用戶對XML文檔的操作和維護(hù)。同時我們需要注意的是XML是一種開放的結(jié)構(gòu)體系并不依賴于任何一家公司,所以開發(fā)基于XML的應(yīng)用必然會得到絕大多數(shù)軟件開發(fā)平臺的支持。另外,我們也可以看到,象微軟這樣的軟件開發(fā)主流企業(yè)也把目光定位在基于XML+COM的體系上,無論是微軟的Office系列、Web服務(wù)器和瀏覽器還是數(shù)據(jù)庫產(chǎn)品(SQL Server)都已經(jīng)開始支持基于XML的應(yīng)用。通過XML來定制應(yīng)用程序的前端,COM來實(shí)現(xiàn)具體的業(yè)務(wù)對象和數(shù)據(jù)庫對象,使系統(tǒng)具有更加靈活的擴(kuò)展性和維護(hù)性。