转载地址: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两种编码。

<span style="font-size:18px;">保存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());}</span>

二、获取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,可能是一些注释或空格行之类,我们需要判断节点类型。

节点类型的种类及说明如下表:

而对于新建的一个xml来说,我们创建IXMLDOMDocument接口后,调用createElement_x函数创建的第一个节点即为root节点。

MSXML应用总结 开发篇(上)相关推荐

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

    原文:http://blog.sina.com.cn/s/blog_48f93b530100eq4b.html 三.查询XML文档节点 这部分属于"读"XML文档并做节点遍历,由于 ...

  2. MSXML应用总结 开发篇(下)

    三.查询XML文档节点 这部分属于"读"XML文档并做节点遍历,由于担心加上实例会占用过多的篇幅影响阅读,先在这篇做方法总结,以后有时间再写一篇"实战篇"专门写 ...

  3. 让kaldi在Linux开发板上运行起来~ (测试运行篇)

    [kaldi各文件解释] /egs:不同语料例子的执行脚本文件 /tools:存放asr过程中用到的库 /src:存放实际执行的c++算法 解码工具(src/onlinebin中): online-g ...

  4. Python从入门到精通 - 入门篇 (上)

    转载自微信公众号:王的机器 0 引言 微信公众号终于可以插代码了,Python 可以走一波了.首先我承认不是硬核搞 IT 的,太高级的玩法也玩不来,讲讲下面基本的还可以,之后带点机器学习.金融工程和量 ...

  5. iot架构 mqtt netty_Netty实现高性能IOT服务器(Groza)之手撕MQTT协议篇上

    前言 诞生及优势 MQTT由Andy Stanford-Clark(IBM)和Arlen Nipper(Eurotech,现为Cirrus Link)于1999年开发,用于监测穿越沙漠的石油管道.目标 ...

  6. Flutter开发之《新锐专家之路:混合开发篇》笔记(55)

    Flutter新锐专家之路:混合开发篇 作者:闲鱼技术-正物 本篇是此系列的第二篇,重点介绍如何让Flutter能够开发,实现业务需求.这部分包括:混合栈的管理,混合下的能力补齐和包管理. 混合栈的管 ...

  7. ajax传递多个base64,H5移动开发Ajax上传多张Base64格式图片到服务器

    这篇文章主要为大家详细介绍了H5移动开发Ajax上传多张Base64格式图片到服务器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 废话不多说,直接看代码吧 1.上传组件 2.展示添加上的图片 v ...

  8. qt 4.8.4 linux,Tslib和Qt 4.8.4与在开发板上的移植

    这篇博客算是接着Linux 下编译.安装.配置 QT这篇的,搞完PC平台的就来弄一下嵌入式平台的,Linux的东西搞起来麻烦的地方就在于太杂.太散,像QT,各版本之间都有很多差异,因此在网络上查找资料 ...

  9. 《CSS蝉意花园读书精记》(基础篇---------上.资料篇1)

    这一篇文章主要是翻译书中提到的国际化的一篇文章,并让大家了解软件开发中字符编码的众多问题,被翻译的文章写得比较早,可能从技术的角度来看不是很有意义的,作者在文中是概括主流的字符编码,并不能让大家深入的 ...

  10. .NET Core实战项目之CMS 第十四章 开发篇-防止跨站请求伪造(XSRF/CSRF)攻击处理...

    通过 ASP.NET Core,开发者可轻松配置和管理其应用的安全性. ASP.NET Core 中包含管理身份验证.授权.数据保护.SSL 强制.应用机密.请求防伪保护及 CORS 管理等等安全方面 ...

最新文章

  1. Vue之for列表渲染、methods事件和model表单绑定
  2. ios可变数组的操作
  3. 2018修复激活闪退_DNA损伤反应与DNA的修复(三)
  4. 20175316 盛茂淞 实验一 Java开发环境的熟悉
  5. SpringCloud(第一部分)
  6. 使用VMware进行基于Ubuntu16.04LTS的Spark集群搭建
  7. 安徽大学计算机考研失败,回馈:2014年安徽大学计算机初试回忆题,我是雷锋,低调...
  8. 视觉SLAM十四讲(2):初识SLAM
  9. 生成证书密钥RequestsDependencyWarning:Old version of cryptography ([1, 2, 3]) may cause slowdown.
  10. Scala基础之变量和数据类型
  11. 心痛!你的快递可能已经被烧毁,13吨快递“无一生还”
  12. 【Elasticsearch】Elasticsearch查询参数batched_reduce_size的解释
  13. svn 导入的 web项目怎么变成了java项目了
  14. sqoop导入数据常见问题解决方法
  15. bat 判断文件名字含有某些字段_PE文件头及其简单逆向运用
  16. 计算机软件专业代码表,2019-04-09 计算机软件适用的国民经济行业代码表
  17. 摩尔庄园手游服务器链接不稳定,摩尔庄园手游公测常见问题解决方法一览
  18. 2007年9月c语言真题及答案,1997年9月二级C语言笔试真题及答案.doc
  19. Go 实现自举的具体含义
  20. 笔记:《高效能人士的七个习惯》第五章 习惯三 要事第一——自我管理的原则

热门文章

  1. ACDSee 15/ACDSee Pro 6简体中文版破解注册机
  2. Python自动化模拟键盘操作
  3. NRF51822---AD采样(连载5)
  4. css html颜色,CSS颜色
  5. ubuntu下格式化被写保护的U盘
  6. 电感耦合等离子体发射光谱法测定水样中的金属含量
  7. Java setlocale方法_Java MessageFormat setLocale()用法及代码示例
  8. linux 查找文件及根据条件搜索文件内容
  9. R语言使用aov函数进行单因素方差分析(One-way ANOVA)、使用multcomp包的glht函数检验组均值之间所有成对对比差异、使用plot函数可视化Tukey HSD两两均值比较图
  10. PDF提取图片(错误纠正)