利用VC++?/font>MSXML解析XML文
一?/span>文档对象模型Q?font face="Times New Roman">DOMQ?/font>
DOM?/font>Document Object ModelQ文对象模型)的简Uͼ是对XML文q行应用开发、编E的应用E序接口Q?/font>APIQ。作?/font>W3C公布的一U跨q_、与语言无关的接口规范,DOM提供了在不同环境和应用中的标准程序接口,可以用Q何语a实现?/font>
DOM采用对象模型和一pd的接口来描述XML文的内容和l构Q即利用对象把文模型化。这U对象模型实现的基本功能包括Q?/font>
?nbsp;描述文表示和操作的接口Q?/font>
?nbsp;接口的属性和Ҏ(gu)Q?/font>
?nbsp;接口之间的关pM及互操作?/font>
DOM可对l构化的XML文q行解析Q文中的指令、元素、实体、属性等所有内容个体都用对象模型表C,整个文被看成是一个有l构?/font>信息?/span>Q而不是简单的文本,生成的对象模型就是树(wi)的节点,对象同时包含?/span>Ҏ(gu)?/span>属?/span>。因此,Ҏ(gu)档的所有操作都是在对象?/span>上的q行。在DOM中,?wi)中的一切都是对象,不管是根节点q是实体的属性?/font>
?font face="Times New Roman">DOM中主要有以下三个对象Q?/font>
?/font> XML文对象
XML文既是一U对象,同时又代表整?/font>XML文。它?/font>根元?/span>?/span>子元?/span>l成?/span>
?/font> XML节点对象
XML节点对象代表的是XML文内部的节点,如元素、注释、名字空间等?/font>
?nbsp;XML节点列表
XML文模块列表代表了节点的集合?/font>
利用DOMQ开发h员可以动态地创徏XML文档Q?/font>遍历l构Q?/span>d、修攏V删?/span>内容{。其面向对象的特性,使h们在处理XML解析相关的事务时节省大量的精力,是一U符合代码重用思想的强有力~程工具?/font>
二?font face="Times New Roman">DOM的四个基本接?/font>(引用自:(x)http://bbs.xml.org.cn/dispbbs.asp?boardID=11&ID=9220)
?font face="Times New Roman">DOM接口规范中,有四个基本的接口Q?font face="Times New Roman">DocumentQ?/font>NodeQ?/font>NodeList以及NamedNodeMap。在q四个基本接?nbsp;中,Document接口是对文q行操作的入口,它是?/font>Node接口l承q来的?/font>Node接口是其他大多数接口的父c,?nbsp;DocumetQ?/font>ElementQ?/font>AttributeQ?/font>TextQ?/font>Comment{接口都是从Node接口l承q来的?/font>NodeList接口是一个节点的集合Q它包含了某个节点中的所有子节点?/font>NamedNodeMap接口也是一个节点的集合Q通过该接口,可以建立节点名和节点之间的一一映射关系Q从而利 用节点名可以直接讉K特定的节炏V下面将对这四个接口分别做一些简单的介绍?/font>
1?/font>Document接口
Document接口代表了整?/font>XML/HTML文Q因此,它是整棵文?wi)的根,提供了对文中的数据q行讉K和操作的入口?/font>
׃元素、文本节炏V注释、处理指令等都不能脱L的上下文关p而独立存在,所以在Document接口提供了创建其他节点对象的Ҏ(gu)Q通过该方法创建的节点对象都有一?/font>ownerDocument属性,用来表明当前节点是由谁所创徏的以及节点同Document之间的联pR?/font>
?font face="Times New Roman">DOM?wi)中Q?/font>Document节点?/font>DOM?wi)中的根节点Q也卛_XML文q行操作的入口节炏V通过Docuemt节点Q可以访问到文中的其他节点Q?nbsp;如处理指令、注释、文档类型以?/font>XML文的根元素节点{等。另外,在一?/font>DOM?wi)中Q?/font>Document节点可以包含多个处理指o、多个注释作为其子节 点,而文档类型节点和XML文根元素节炚w是唯一的?/font>
关于Document接口?/font>IDLQ?/font>Interface Definition Language接口定义语言Q定义和其中一些比较常用的属性和Ҏ(gu)的详l介l可以在MSDN中找到?/font>
2?/font>Node接口
Node接口在整?/font>DOM?wi)中h举轻重的地位,DOM接口中有很大一部分接口是从Node接口l承q来的,例如Q?/font>Element?/font>Attr?/font>CDATASection{接口,都是?/font>Nodel承q来的。在DOM?wi)中Q?/font>Node接口代表了树(wi)中的一个节炏V?/font>
3?/font>NodeList接口
NodeList接口提供了对节点集合的抽象定义,它ƈ不包含如何实现这个节炚w的定义?/font>NodeList用于表示有顺序关pȝ一l节点,比如某个节点的子节点序列。另外,它还出现在一些方法的q回gQ例?/font>GetNodeByName?/font>
?font face="Times New Roman">DOM中,NodeList的对象是"live"的,换句话说Q对文的改变,?x)直接反映到相关?/font>NodeList对象中。例如,如果通过DOM获得一 ?/font>NodeList对象Q该对象中包含了某个Element节点的所有子节点的集合,那么Q当再通过DOM?/font>Element节点q行操作Q添加、删除、改 动节点中的子节点Q时Q这些改变将?x)自动地反映?/font>NodeList对象中,而不需DOM应用E序再做其他额外的操作?/font>
NodeList中的每个item都可以通过一个烦引来讉KQ该索引g0开始?/font>
4?/font>NamedNodeMap接口
实现?font face="Times New Roman">NamedNodeMap接口的对象中包含了可以通过名字来访问的一l节点的集合。不q注意,NamedNodeMapq不是从NodeListl?nbsp;承过来的Q它所包含的节炚w中的节点是无序的。尽这些节点也可以通过索引来进行访问,但这只是提供了枚?/font>NamedNodeMap中所包含节点的一U简 单方法,q不表明?/font>DOM规范中ؓ(f)NamedNodeMap中的节点规定了一U排列顺序?/font>
NamedNodeMap表示的是一l节点和其唯一名字的一一对应关系Q这个接口主要用在属性节点的表示上?/font>
?font face="Times New Roman">NodeList相同Q在DOM中,NamedNodeMap对象也是"live"的?/font>
三?font face="Times New Roman">MSXML
从理Z_(d)Ҏ(gu)XML的格式定义,我们可以自己~写一?/font>XML的语法分析器Q但实际上微软已l给我们提供了一?/font>XML语法解析器,即一个叫?nbsp;MSXML.DLL的动态链接库Q实际上它是一?/font>COMQ?/font>Component Object ModelQ对象库Q里面封装了q行XML解析时所需要的所有对象。因?/font>COM是一U以二进制格式出现的和语a无关的可重用对象Q所以你可以用Q何语a (比如VBQ?/font>VCQ?/font>DELPHIQ?/font>C++ Builder甚至是脚本语a{等)对它q行调用Q在你的应用中实现对XML文档的解析?/font>
MSXML.DLL所包括的主?/font>COM接口有:(x)
1. IXMLDOMDocument(Document接口)
DOMDocument对象?/font>XML DOM的基Q你可以利用它所暴露的属性和Ҏ(gu)来浏览、查询和修改XML文的内容和l构?/font>DOMDocument表示了树(wi)的顶层节点,它实CDOM?nbsp;的所有的基本Ҏ(gu)Qƈ且提供了额外的成员函数来支持XSL?/font>XSLT。它创徏了一个文对象,所有其他的对象都可以从q个文档对象中得到和创徏?/font>
2. IXMLDOMNode(Node接口)
IXMLDOMNode是文档对象模?/font>(DOM)中的基本对象Q元素、属性、注释、过E指令和其他的文组仉可以认ؓ(f)?/font>IXMLDOMNode。事实上Q?/font>DOMDocument对象本n也是一?/font>IXMLDOMNode对象?/font>
3. IXMLDOMNodeList
IXMLDOMNodeList实际上是一个节?/font>(Node)对象的集合,节点的增加、删除和变化都可以在集合中立d映出来,可以通过"for.循环 "l构来遍历所有的节点?/font>
4. IXMLDOMParseError
IXMLDOMParseError接口用来q回在解析过E中所出现的详l的信息Q包括错误号、行受字W位|和文本描述?/font>
在具体应用时可以?font face="Times New Roman">DOMDocument?/font>LoadҎ(gu)来装?/font>XML文Q用IXMLDOMNode ?/font>selectNodesQ查询的l果有多个,得到存放搜烦l果的链表)?/font>selectSingleNodeQ查询的l果有一个,在有多个的情况下q回?nbsp;到的W一个节点)Ҏ(gu)q行查询Q用createNode?/font>appendChildҎ(gu)来创点和q加节点Q用IXMLDOMElement?nbsp;setAttribute?/font>getAttributeҎ(gu)来设|和获得节点的属性?/font>
四、编ED?/p>
1、目标文:(x)
<book id="bk101">
<author>lizlex</author>
<title>XML Developer's Guide</title>
</book>
2、步骤:(x)
(1)在StdAfx.h中引入动态链接库 MSXML.DLL(C:\windows\system32\msxml4.dll)
#import <msxml4.dll>
(2)界面设计Q?br>分别攑օ三个TextQ用于输入数据,与显C文内容用Qƈd兌的成员变量m_strId,m_strAuthor, m_strTitleQƈd定按钮Q?br>
(3)产生文档的程序片?br>void CXmlparseDlg::OnButtonGenerate()
{
UpdateData();
MSXML2::IXMLDOMDocumentPtr pDoc;
MSXML2::IXMLDOMElementPtr xmlRoot ;
//创徏DOMDocument对象
HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));
if(!SUCCEEDED(hr))
{
MessageBox("无法创徏DOMDocument对象Q请查是否安装了MS XML Parser q行?");
return ;
}
//根节点的名称为Book
//创徏元素q添加到文档?/span>
xmlRoot=pDoc->createElement((_bstr_t)"Book");
//讄属?/span>
xmlRoot->setAttribute("id",(const char *)m_strId);
pDoc->appendChild(xmlRoot);
MSXML2::IXMLDOMElementPtr pNode;
//d“author”元素
pNode=pDoc->createElement((_bstr_t)"Author");
pNode->Puttext((_bstr_t)(const char *)m_strAuthor);
xmlRoot->appendChild(pNode);
//d“Title”元素
pNode=pDoc->createElement("Title");
pNode->Puttext((const char *)m_strTitle);
xmlRoot->appendChild(pNode);
//保存到文?br> //如果不存在就建立,存在p?/span>
pDoc->save("d:\\he.xml");
}
(4)dXML文档的程序片?br>void CXmlparseDlg::OnButtonLoad()
{
MSXML2::IXMLDOMDocumentPtr pDoc;
HRESULT hr;
hr=pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));
if(FAILED(hr))
{
MessageBox("无法创徏DOMDocument对象Q请查是否安装了MS XML Parser q行?");
return ;
}
//加蝲文g
pDoc->load("d:\\he.xml");
MSXML2::IXMLDOMNodePtr pNode;
//在树(wi)中查扑为Book的节?"//"表示在Q意一层查?/span>
pNode=pDoc->selectSingleNode("//Book");
MSXML2::DOMNodeType nodeType;
//得到节点cd
pNode->get_nodeType(&nodeType);
//节点名称
CString strName;
strName=(char *)pNode->GetnodeName();
//节点属?攑֜链表?/span>
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);
//取得节点的?/span>
pAttrItem->get_nodeTypedValue(&variantValue);
m_strId=(char *)(_bstr_t)variantValue;
UpdateData(FALSE);
}
]]>