XML文件解析(在Windows环境MFC程序中,使用自带的MSXML6.dll解析)

文章介绍了如何使用MSXML的DOM接口处理XML文档,包括初始化COM库、创建DOMDocument对象、加载XML字符串、查找和遍历节点以及获取属性值。推荐使用智能指针管理COM对象的引用计数,以简化内存管理。
摘要由CSDN通过智能技术生成

主要总结一下MSXML DOM接口的应用。DOM(Document Object Model) 是微软提供的处理XML文档的一个API标准库,我们可以将其理解为一组抽象了XML文档结构的接口。

MSXML的DOM模型是符合W3C DOM标准的,而DOM API在Windows中COM接口的形式提供(所以,使用MSXML时候初始化COM库),关于COM请大家查阅相关资料。简单来说,COM提供了一个环境和一套规则,使接口的设计实现到对象的创建、使用和释放都标准化,从而使COM支持跨平台和跨语言;更重要的是,遵守COM规范使我们代码的接口与实现分离,将程序框架的稳定与扩展统一起来,对于使用COM接口的人则更加简单直观。COM中很重要的概念是refcount,即接口对象的访问计数,通过AddRef和Release两个接口函数来控制。要想用好refcount还是件比较困难的事情,因此我推荐大家使用智能指针。使用智能指针就像使用简单指针一样,我们完全不用去关心指针指向内存空间的释放。

// msxml.cpp : 定义控制台应用程序的入口点。
 
#include "stdafx.h"
#include <iostream>
#include <atlstr.h>

#import <MSXML6.dll>  //注意点1:这里要导入dll

using namespace MSXML2;
using namespace std;
 
void msxml2_init()
{
    ::CoInitialize(NULL); //注意点2:必须先初始化COM(应用程序调用com库函数之前,必须初始化com库)
}
 
void msxml2_del()
{
    ::CoUninitialize();   //注意点3:关闭当前线程的COM库。卸载线程加载的所有dll,释放任何其他的资源,关闭在线程上维护所有的RPC连接。
}

/* nodename: 要查找的节点的名字
* xmbuf: xml字符串
* 函数功能:查找目标节点的所有属性值
*/
void find_node_attr(char *nodename, char *xmlbuf)
{
    MSXML2::IXMLDOMDocumentPtr pDoc;
    HRESULT hr;
    hr=pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument60));
    if(FAILED(hr))
    {
        printf("无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库!\n");
        return ;
    }
    /* 加载xml字符串 */
    pDoc->loadXML(xmlbuf);
 
    MSXML2::IXMLDOMNodePtr pRoot_node, pNode;
    MSXML2::IXMLDOMNamedNodeMapPtr pAttrs;
    MSXML2::IXMLDOMNodePtr pAttrItem;
    long nCount;
 
    /* 在树中查找名为Book的节点,"//"表示在任意一层查找 */
    char tmpnodename[] = "//";
    strncat(tmpnodename, nodename, );
    pNode = pDoc->selectSingleNode(tmpnodename);
    /* get_attributes()来获取该节点的所有属性列表 */
    pNode->get_attributes(&pAttrs);
 
    pAttrs->get_length(&nCount);
    cout << "共有" << nCount << "个属性值" << nCount << endl;
    for(int i =  ; i < nCount ; i++)
    {
        pAttrs->get_item(i, &pAttrItem);
        /* nodeName, nodeTypedValue得到属性名和属性值 */
        cout << (_bstr_t)pAttrItem->nodeName << ":" ;
        cout << (_bstr_t)pAttrItem->nodeTypedValue << endl;
    }    
 
    //使用过了的指针要释放。未使用的指针不要释放,否则会触发中断错误。
    pDoc.Release();
    pNode.Release();
    pAttrs.Release();
    pAttrItem.Release();
}
 
/*
* 函数功能:遍历整个xml_buf的内容并打印节点名字和节点的属性值
*/
void print_xmlnode(char *xmlbuf)
{    
 
    MSXML2::IXMLDOMDocumentPtr pDoc;
    HRESULT hr;
    hr=pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument60));
    if(FAILED(hr))
    {
        printf("无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库!\n");
        return ;
    }
    /* 加载xml字符串 */
    pDoc->loadXML(xmlbuf);
 
    MSXML2::IXMLDOMNodePtr  pGwsIp_node, pRoot_node, pNode;
    MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;
    MSXML2::IXMLDOMNodePtr pAttrItem;
 
    /* 遍历整个xml_buf的内容并打印节点名字和节点的属性值 */
    pRoot_node = pDoc->firstChild;
    pGwsIp_node = pRoot_node->firstChild;//pDoc->firstChild->firstChild;
    MSXML2::DOMNodeType nodeType;
    long nCount ;
 
    //节点名称 root下子节点的个数
    unsigned int num = pRoot_node->childNodes->length;
    cout << "num = " << num << endl;
    char node_name[] = {};
    //Gettext()获取节点值
    for(int i = ; i < num; i++) {
        strcpy(node_name, pRoot_node->childNodes->item[i]->Gettext());
        cout << "node_name = " << node_name << endl;
    }
 
    /*IXMLDOMNamedNodeMap是xml中描述一个结点属性的接口,
    通过它用户可以对某个节点的属性进行操作*/
    pGwsIp_node->get_attributes(&pAttrs);
    pAttrs->get_length(&nCount);
 
    for(int i =  ; i < nCount ; i++)
    {
        pAttrs->get_item(i,&pAttrItem);
        /*get_nodeName,get_nodeTypedValue得到属性名和属性值*/
        cout << (_bstr_t)pAttrItem->nodeName << ":" ;
        cout << (_bstr_t)pAttrItem->nodeTypedValue << endl;
    }
    //使用过了的指针要释放。未使用的指针不要释放,否则会触发中断错误。
    pDoc.Release();
    pRoot_node.Release();
    pGwsIp_node.Release();
    pAttrs.Release();
    pAttrItem.Release();
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    msxml2_init();//初始化COM库
 
    char buf[] = "<gwsctrl><gws ip=\"192.168.1.24\" emac=\"D4:CA:6D:35:0D:95\" wmac=\"D4:CA:6D:11:59:9F\"/><A>一个节点</A><B>二个节点</B></gwsctrl>";
    find_node_attr("gws",  buf);
    print_xmlnode(buf);
 
    getchar();
    msxml2_del();//关闭当前线程的COM库
    
    return ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值