【转载】MSXML应用总结 开发篇(上)

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

本篇是接前文“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节点。

时间: 2024-10-13 12:55:53

【转载】MSXML应用总结 开发篇(上)的相关文章

【转载】MSXML应用总结 开发篇(下)

原文:http://blog.sina.com.cn/s/blog_48f93b530100eq4b.html 三.查询XML文档节点 这部分属于“读”XML文档并做节点遍历,由于担心加上实例会占用过多的篇幅影响阅读,先在这篇做方法总结,以后有时间再写一篇“实战篇”专门写个实例工程,可以有更完整的参考代码. 查询和遍历XML文档的大致步骤:创建IXMLDOMDocument接口对象 -> load加载文档 -> 得到root节点 -> 依次遍历各节点.也可以通过IXMLDOMDocume

[转载]在iTOP-4412开发板上调试helloworld应用

本文转自迅为论坛:http://www.topeetboard.com 1.安装ADB驱动 在开发板上调试 Android 应用,首先要安装 ADB 驱动. 通过“SDK Manager.exe”来安装.如下图所示.另外需要注意的是,如果要使用 SDK Manager 安装软件,需要将 Eclipse 关闭. 安装完成后,打开文件夹中“USB_fastboot_tool\platform-tools”的命令行 cmd.exe, 如下图所示,输入命令“#adb”,然后回车.这里集成了 adb 命令

前端开发工程师 - 03.DOM编程艺术 - 第1章.基础篇(上)

第1章.基础篇(上) DOM (Document Object Model) - 文档对象模型 以对象的方式来表示对应的html,它有一系列的规范 i.e. 在浏览器中,DOM是通过JS实现的. DOM: DOM Core:核心结构.API的定义 DOM HTML: 定义HTML如何转化成对象(HTML对应的对象)-- 操作节点 DOM Style:样式转换成对象 -- 操作样式 DOM Event:事件对象的模型 -- 响应用户的操作 文档树 HTML -> DOM树 节点遍历 node.pa

R的极客理想——高级开发篇

这篇是计算机类的优质预售推荐>>>><R的极客理想--高级开发篇> 资深R语言用户多年实战经验的结晶 编辑推荐 资深R语言用户多年实战经验的结晶,介绍R语言本身的核心技术以及R语言在不同领域的跨学科综合应用,借助每日中国天气的应用案例和游戏开发的案例,揭秘完整的R包开发流程,帮助读者创建自己的R包,打开R语言产品化的思路. 内容简介 本书的内容来自作者使用R语言的实践经验总结,以R语言的高级编程为主,辅以跨界知识的综合运用,涉及计算机.统计.数学.金融四个学科的知识.书

【COCOS CREATOR 系列教程之二】脚本开发篇&事件监听、常用函数等示例整合

[Cocos Creator ](千人群):  432818031 上一篇,介绍了Himi在使用过cc所有组件后的一篇总结,没有具体介绍每个组件的原因在于官方文档很齐全,而且也有视频的介绍. 所以希望童鞋们可以把我这两篇博文当成对组件.脚本两部分开发的整理与总结. 后续的文章,Himi应该主要更新一些官方还未补充或者还没有的教程.避免无用功. 下面直接放出代码,因为不是很难理解.所以不再一一赘述,都是常用的函数.事件监听.动作回调.定时器等开发过程中必接触的. 大致内容如下: cc 属性介绍 获

[Android Memory] App调试内存泄露之Context篇(上)

转载自:http://www.cnblogs.com/qianxudetianxia/p/3645106.html Context作为最基本的上下文,承载着Activity,Service等最基本组件.当有对象引用到Activity,并不能被回收释放,必将造成大范围的对象无法被回收释放,进而造成内存泄漏. 下面针对一些常用场景逐一分析. 1. CallBack对象的引用 先看一段代码: @Override protectedvoid onCreate(Bundle state){ super.o

【Android 系统开发】 编译 Android 系统 u-boot 内核 源码 并烧写到 OK-6410A 开发板上

博客地址 : http://blog.csdn.net/shulianghan/article/details/40299813  本篇文章中用到的工具源码下载 : -- ok-6410A 附带的 Android 光盘 下载地址 : http://pan.baidu.com/share/link?shareid=3662728609&uk=2754759285 ; -- 光盘所含内容 : Android 引导 u-boot 源码, Android 内核 源码, Android 系统源码, 交叉编

Jetty JNDI开发实战(上)

Jetty JNDI开发实战(上) 作者:chszs,版权所有,未经同意,不得转载.博主主页:http://blog.csdn.net/chszs 一.JNDI介绍 JNDI即Java Naming and Directory Interface,Java命名和目录接口,是Oracle公司提供的一种标准的Java命名系统接口,允许Java客户端根据命名发现或查询数据和对象.JNDI规范提供了一组标准的独立于命名系统的API,这些API构建在与命名系统有关的驱动之上,有助于将应用与实际的数据源相分

开发板上使用core文件调试

转载:http://www.nginx.cn/1521.html 如果开发板的操作系统也是linux,core调试方法依然适用.如果开发板上不支持gdb,可将开发板的环境(依赖库).可执行文件和core文件拷贝到PC的linux下.在 PC上调试开发板上产生的core文件,需要使用交叉编译器自带的gdb,并且需要在gdb中指定solib-absolute-prefix和 solib-search-path两个变量以保证gdb能够找到可执行程序的依赖库路径.有一种建立配置文件的方法,不需要每次启动