VC++和MSXML解析XML文档

最近研究起了使用VC6.0进行解析XML文档,而对于XML文档的解析目前网上主要使用了两种方法:MSXML和CMarkUp类。而我就先从最基本的DOM研究起了。而对于DOM主要采用微软提供的MSXML库,另外好像还有第三方库TinyXML,咱就不研究了。

而对于MSXML的使用,网上别人提供的东西都比较零碎,而且还比较乱,在论坛上问反而被一堆人鄙视,得到的解答少之又少。于是我专门花了一天的时间研究了下,现在小有成果,就感觉整理了一些,以供和我一样初级选手作为入门的资料。当然,在整理过程中还是会出现错误,望大家发现后指正。如果你感觉文章还好的话就留个足迹,顶顶人气哈。

闲话到此为止,下面进入正题:

 

1. 开发环境

系统中须保证已经安装了msxml。以下均针对msxml4版本进行的操作,而对msxml6的版本则需要进行相应的改动即可。

编程开发环境Visual C++ 6.0

2. 具体开发实现

2.1 导入库

在使用msxml之前,第一步要做的就是导入该库。导入msxml4库需要进行以下操作:

#include "msxml.h" 

#import "C:/windows/system32/msxml.dll" rename_namespace("xml")

即:首先要包含头文件,然后在导入库,并重新定义了一个命名空间,这样为了以后使用的方面。

2.2 初始化com

因为该库为COM组件,故使用前需要初始化com组件库。

AfxOleInit(); 或是 ::CoInitialize(NULL); // 初始化Com组件。

 

同时,若不再使用该MSXML组件时,可以释放组件占用的内存。

::CoUninitialize();

 

以上两步做完之后就可以使用DOM库了。

2.3 文档类:IXMLDOMDocumentPtr

Document节点代表了整个的XML文档。当DOM解析一个XML文档后,由XML形成的DOM节点树以Document对象的形式展现给应用程序的。由于XMl文档的元素、处理指令、注释等都处于一个XML文档范围之内,Document中包含了用于创建元素、属性、注释、处理指令等其它节点类型的方法。

因此,首先要创建XML文档类对象

xml::IXMLDOMDocumentPtr pDoc;

 

// 创建DOC类,注意是 ' . ',而不是 ' -> ',尽管它是一个指针。

HRESULT hr = pDoc.CreateInstance(_uuidof(xml::DOMDocument));

if(!SUCCEEDED(hr))

{

AfxMessageBox("无法创建DM对象!");

return;

}

创建完成了Document文档类对象之后就可以进行下一步的创建XML或是解析操作了。

 

以下介绍一些常用的方法:

1) 创建元素:XMLDOMDocument->createElement(name);

2) 创建节点:XMLDOMDocument->createNode(name);

3) 添加节点:XMLDOMDocument->appendChild();

4) 保存生成XML文档:XMLDOMDocument->save();

5) 加载XML文档:XMLDOMDocument->load("path.xml");

6) 获取根节点:XMLDOMDocument->get_documentElement(&root)

 

以上几个方法基本上就可以创建和解析一个简单的XML文档了。

2.4 节点类:IXMLDOMNode

DOM是由一组抽象化的接口组成。Node是整个DOM中最基本的数据类型,它代表了一个抽象的节点。XML文档的DOM树上的具体节点类型都是由Node类型派生而来。

其提供的常用属性或方法如下:

(1)子节点操作

  •  
    •  childNodes:子节点列表。
    •  get_childNodes ():获取子节点列表。
    •  appendChild():添加子节点。
    •  hasChildNodes():判断是否含有子节点。若有返回true
    •  insertBefore():插入子节点。
    •  removeChild():删除子节点。
    •  replaceChild():替换子节点。

2)查询节点

 selectNodes()

运用专门的模式匹配方法匹配要查询的节点,并返回满足要求的节点列表。

 selectSingleNode()

运用专门的模式匹配方法匹配要查询的节点,并返回满足要求的第一个节点。

3)节点名

 nodeName:属性,指示了节点的名称。

 get_nodeName():返回节点名称。

4)节点类型

 nodeType:属性,指示了节点的类型。

节点类型有:NODE_ELEMENTNODE_ATTRIBUTENODE_TEXT NODE_ENTITYNODE_PROCESSING_INSTRUCTION NODE_DOCUMENTNODE_DOCUMENT_TYPE等。

 Get_nodeType():返回该节点的类型。

5)节点值

  •  
    • nodeValue:代表了节点的text值。
    • put_nodeValue():设置节点值。
    • get_nodeValue():获取节点值。

6)节点文本值

  •  
    •  text:代表节点和其子树的text值。
    •  put_text():设置text
    •  get_text():获取text

7)节点属性

  •  
    •  attributes:包含了节点的属性列表。
    •  get_attributes():获取节点属性列表。

 

其中更详细信息请参考MSDN

2.5 XML文档序Prolog类:IXMLDOMProcessingInstructionPtr

文档序需要由Document类创建,如:

xml::IXMLDOMProcessingInstructionPtr head;

head = pDoc->createProcessingInstruction(_bstr_t(_T("xml")),

_bstr_t(_T("version='1.0' encoding='UTF-8'")));

pDoc->appendChild(head); // 将序添加到文档类中。

2.6 元素类:IXMLDOMElementPtr

该节点继承自IXMLDOMNode。其具体属性和方法同IXMLDOMNodePtr,不再细述。

2.7 命名的节点表IXMLDOMNamedNodeMap

通过属性节点集合实现对命名空间和迭代的支持。IXMLDOMNamedNodeMap为一个节点集,并且支持通过名称或标签值的访问。该集合主要应用于对属性的支持。

如若想解析一个元素的属性,可用以下操作实现:

IXMLDOMNamedNodeMapPtr pAttrMap = NULL;

IXMLDOMElementPtrproot->get_attributes(&pAttrMap);

long  count;

BSTR content, name;

pAttrMap->get_length(&count);

pAttrMap->get_item(0, &pAttrItem);

pAttrItem->get_text(&content);

pAttrItem->get_nodeName(&name);

该类所提供的属性和方法有:

  •  
    •  length:该集合中的属性个数。
    •  get_length():获取length
    •  getNamedItem():检索指定名称的属性。
    •  getQualifiedItem():返回指定名称空间和属性名称的属性。

其它见CSDN技术文档。

2.8 属性类:IXMLDOMAttribute

指示了元素IXMLDOMElement的一个属性。属性继承于IXMLDOMNode类,但不不属于元素的一个子节点,同样也不属于文档树的一个节点。

其具体属性和方法也不做详细介绍,具体可参考CSDN技术文档。

2.9 释放元素

在使用完节点(IXMLDOMNode,包括其子类)之后,需要释放其所占用的资源,否则会造成消耗大量系统内存资源。释放使用如下操作:

Node->Release();

Doc->Release();

 

3. 具体实例

3.1 创建XML文档

xml::IXMLDOMDocumentPtr pDoc; // Document文档类 xml::IXMLDOMElementPtr xmlRoot; // 元素类,用于存放根元素 xml::IXMLDOMNodePtr xmlNode; // 节点类 HRESULT hr = pDoc.CreateInstance(_uuidof(xml::DOMDocument)); if(!SUCCEEDED(hr)) { AfxMessageBox("无法创建DM对象!"); return; } //--------------------------创建序Prolog------------------------------------- xml::IXMLDOMProcessingInstructionPtr head; head = pDoc->createProcessingInstruction(_bstr_t(_T("xml")), _bstr_t(_T("version='1.0' encoding='UTF-8'"))); pDoc->appendChild(head); // 将序添加到文档类中。 //-------------------------创建带有属性的根元素----------------------------- _variant_t varTyp((short)xml::NODE_ELEMENT); xmlRoot = pDoc->createElement("People"); xmlRoot->setAttribute("id",(_bstr_t)(_T(m_ID))); // m_ID为CString型 pDoc->appendChild(xmlRoot); // 将根元素添入文档类中 // -------------------------创建子元素,采用两种方法----------------------- xmlNode = pDoc->createNode(varTyp, "Name", ""); xmlNode->put_text(_bstr_t(_T(m_name))); // m_name为CString型 xmlRoot->appendChild(xmlNode); xmlNode = pDoc->createElement("Profession"); xmlNode->text = (_bstr_t)(_T(m_work)); // m_work为CString型 xmlRoot->appendChild(xmlNode); //-------------------------------------------------------------------- pDoc->save("d://people.xml"); // 保存XML文档 

 

如此得到的XML文档为:

零零喜

大内密探

实际中,可能会出现排版问题。比如元素及子元素均放在一行中,这也是我咱是还没解决的。

3.2 解析XML文档

其中实例如下:

xml::IXMLDOMDocumentPtr pdoc; // XML文档类 BSTR name, content; // 用于保存节点的名称以及节点内容 xml::DOMNodeType type; // 定义节点类型变量 int i; //----------------------------创建文档类--------------------------------- HRESULT hr = pdoc.CreateInstance(_uuidof(xml::DOMDocument)); if(!SUCCEEDED(hr)) { AfxMessageBox("无法创建DOM对象!"); return; } pdoc->load("d://people.xml"); // 导入XML文档 //----------------------------获取根节点------------------------------------ //XML文档元素指针,初始化指向根节点;注意相当于数据库database xml::IXMLDOMElementPtr proot=NULL; hr=pdoc->get_documentElement(&proot); if((!SUCCEEDED(hr))) { AfxMessageBox("获取根节点有误!"); return; } //--------------测试根节点--------------- CString str; proot->get_nodeName(&name); str = name; proot->get_text(&content); str = content; proot->get_nodeType(&type); //------------------获取根节点属性------------------- // 节点属性,放在链表中 xml::IXMLDOMNamedNodeMapPtr pAttrMap = NULL; xml::IXMLDOMNodePtr pAttrItem; proot->get_attributes(&pAttrMap); long count; pAttrMap->get_length(&count); // 节点属性表的属性个数 pAttrMap->get_item(0, &pAttrItem); // 读取第一个属性 pAttrItem->get_text(&content); // 属性值 str = content; pAttrItem->get_nodeName(&name); // 属性名称 str = name; //----------------------------获取根元素的子元素列表--------------------------- //获取子节点链表;注意相当于表table;或者相当于记录recordset xml::IXMLDOMNodeListPtr pnodelist; hr=proot->get_childNodes(&pnodelist); //获取子节点链表中的个数;注意相当于得到记录的个数 long productNum=0; hr=pnodelist->get_length(&productNum); // 计算子元素个数 //----------------------------测试子元素内容以及名称等---------------------------- xml::IXMLDOMNodePtr pnode = NULL; for( i=0; iget_item(i, &pnode); // 获取子元素 CString str; pnode->get_nodeName(&name); str = name; pnode->get_text(&content); str = content; pnode->get_nodeType(&type); } 

 

 

 

你可能感兴趣的:(HTML/XML,xml,vc++,文档,attributes,encoding,processing)