当前位置:C++技术网 > 资讯 > C++快速实现xml文件的xml节点读写

C++快速实现xml文件的xml节点读写

更新时间:2016-05-29 17:08:13浏览次数:1+次

    在C++技术网中,搜索【xml】关键词,可以搜索到一系列文章,介绍了xml的基础知识和编程使用方法。创建xml文件,参考《C++中使用XML文件:生成XML文件》,读取和解析Xml文件,请参考《C++中使用XML文件:读取并解析XML文件》。当然还有其他说明,就不一一列举了。
    如果你的xml中,节点名称都是唯一的,想做快速的xml读写应用,我已经整理好一个简单的xml操作类,可以实现xml节点的快速读写。当然,如果要实现复杂点的xml文档结构,那就参考前面说的,全面学习一下。
    下面是xml读写类的完整代码:
#include <string>
#include  <sstream>
using namespace std;

#import "msxml3.dll" // - 直接在文件中导入,不依赖IDE的导入,移植性好
class CXml
{
public:
    CXml(){}
    ~CXml(){}
    static bool SetValue(string strName,string strValue,string strPath="setting.xml")
    {
        ::CoInitialize(NULL);
        MSXML2::IXMLDOMDocumentPtr XMLDOC;// - XML文档对象
        HRESULT HR = XMLDOC.CreateInstance(__uuidof(MSXML2::DOMDocument30));// - 创建XML文档实例
        XMLDOC->load(strPath.c_str());// - 加载xml文件
        strName = "//"+strName;
        MSXML2::IXMLDOMNodePtr pNode = XMLDOC->selectSingleNode(strName.c_str());
        _variant_t value;
        HRESULT hr = pNode->put_text(_bstr_t(strValue.c_str()));
        pNode.Release();

        XMLDOC->save(strPath.c_str());
        XMLDOC.Release();  // - 释放使用的文档对象
        ::CoUninitialize(); // - 释放COM组件使用环境

        if(SUCCEEDED(hr))
            return true;
        else
            return false;
    }
    static bool SetValue(string strName,int Value,string strPath="setting.xml")
    {
        ostringstream ostr;
        ostr <<Value;
        string str = ostr.str();
        return SetValue(strName,str,strPath);
    }
    static string GetValueStr(string strName,string strPath="setting.xml")
    {
        ::CoInitialize(NULL);
        MSXML2::IXMLDOMDocumentPtr XMLDOC;// - XML文档对象
        HRESULT HR = XMLDOC.CreateInstance(__uuidof(MSXML2::DOMDocument30));// - 创建XML文档实例
        XMLDOC->load(strPath.c_str());// - 加载xml文件
        strName = "//"+strName;
        MSXML2::IXMLDOMNodePtr pNode = XMLDOC->selectSingleNode(strName.c_str());
        _variant_t value;
        pNode->get_nodeTypedValue(&value);
        std::string strValue = _bstr_t(value);
        pNode.Release();

        XMLDOC.Release();  // - 释放使用的文档对象
        ::CoUninitialize(); // - 释放COM组件使用环境
        return strValue;
    }
    static int GetValueInt(string strName,string strPath="setting.xml")
    {
        ::CoInitialize(NULL);
        MSXML2::IXMLDOMDocumentPtr XMLDOC;// - XML文档对象
        HRESULT HR = XMLDOC.CreateInstance(__uuidof(MSXML2::DOMDocument30));// - 创建XML文档实例
        XMLDOC->load(strPath.c_str());// - 加载xml文件
        strName = "//"+strName;
        MSXML2::IXMLDOMNodePtr pNode = XMLDOC->selectSingleNode(strName.c_str());
        _variant_t value;
        pNode->get_nodeTypedValue(&value);
        int Value = (int)value;
        pNode.Release();

        XMLDOC.Release();  // - 释放使用的文档对象
        ::CoUninitialize(); // - 释放COM组件使用环境
        return Value;
    }
};

    我们这个类是基于微软的xml库实现的,如果你是在为Windows平台上,那使用起来是非常简单的。当然,我们的类代码里,已经自动导入了dll,几乎都是拿来就可以用了。提供出来,是鼓励大家学习C++,其实我们C++是有很容易上手的代码的。然而大多数人都不熟,所以感觉一下子无从下手,做个简单的,却总是搞不好,所以就被打击了。然后就投向其他第三方开源库,越好用就越有兴趣。如果你是做跨平台,或者非Windows平台上的,可以直接学习其他平台的xml操作库,如果是Windows的开发,请学着将Windows上的xml库学会。自然,再学其他的xml库使用,甚至自己写一个库都是可以的。
    我这里就是提供这样一个快速使用的xml库,就是基于微软的。代码都是公开的,随便怎么使用。只是为了鼓励你,勇敢的学习吧。
    这个类只有5个函数,而且是静态的,所以可以当做C函数使用。5个函数分别为两个设置xml节点值和三个获取xml节点值得函数,设置xml节点值函数进行了重载,函数名一样,第二个参数分为字符串型和整型,方便使用,其他参数一样的,设置整型值函数内部调用设置字符串类型的函数,只是在内部将整型格式化为字符串而已,起到一个中转作用,这样做是简化代码。格式化字符串代码如果不懂,请参考《C++如何格式化字符串,超简单实现C++格式化字符串功能》。
    而获取xml节点值也是在最后获取值后,进行了强制转换。在内部转换实现多个版本函数,主要是为了使用方便,不需要调用者进行类型转换。都是为了便于使用,降低使用成本。不然使用者还得熟悉_variant_t类型。
    五个函数的代码差不多,主要的区别就是获取节点值和设置节点值,然后还有保存xml文件,其他基本一样。函数里都完整的实现了xml库的初始化,文件加载,获取节点值,和xml释放等工作。这样设计的目的是降低函数的耦合性,尽可能使每一个函数可以独立使用,这样代码移植性更高。
    MSXML库本身的解释,请在C++技术网搜索xml关键词,搜索到的文章就是这个库的解释了,就不再这里重复。本文主要提供这个库的快速使用。
    一定要注意,我们这个类很简单,只能处理节点名称唯一的场景,只要你要修改的节点名称是唯一的就行了。不修改的节点名称重复无所谓,因为我们这里查找节点是按照名称查找的。
    下面的是适用的:
<txt>
<name>张三</name>
<age>12</age>
</txt>
    下面是不适用的,因为节点名称name重复了,你要得到【李四】节点,就有问题了:
<txt>
<name>张三</name>
<name>李四</name>
</txt>
    至于重复名称的节点的获取,你可以熟悉之后,将重复名称节点处理一下,基本思路就是根据父节点或者节点属性来筛选。只要你保证节点名称不重复,就可以了。这个可以满足很多需求了。当然,如果需求不满足时,你就需要给这个类添加功能支持了。