通过libxml2更新XML的属性值和元素值

来源:互联网 发布:罗其胜网络班教程 编辑:程序博客网 时间:2024/06/08 17:08
场景:1.有时候配置软件的全局设置项时,需要用到键值对的存储方式。2.配置信息不多的情况下.数据库太重量级,文本文件对utf8编码又不好,即中文内容,这时候XML文件是最佳选择。
 
//这里使用的是libxml2-2.7.1版本库
 
#include <iostream>#include <string.h>#include <libxml/xmlmemory.h>#include <libxml/parser.h>#include <libxml/parserInternals.h>#include <libxml/HTMLparser.h>#include <libxml/HTMLtree.h>#include <libxml/tree.h>#include <libxml/xpath.h>#include <libxml/debugXML.h>#include <libxml/xmlerror.h>#include "libxml/encoding.h"//#include <tchar.h>using namespace std;void UpdateNodeValue(xmlNode* node, const char *value){    xmlChar *xml_value = xmlCharStrdup(value);    xmlNodeSetContent(node, xml_value);    xmlFree(xml_value);}void UpdateAttrValue(xmlNode* node, const char *attr_name, const char *value){    xmlChar *xml_prop_name = xmlCharStrdup(attr_name);    xmlChar *xml_prop_value = xmlCharStrdup(value);    xmlSetProp(node, xml_prop_name, xml_prop_value);    xmlFree(xml_prop_value);    xmlFree(xml_prop_name);}xmlXPathObjectPtr GetXPathObject(xmlDocPtr doc, const char* key){    //获取xpath上下文    xmlXPathContextPtr context = xmlXPathNewContext(doc);    if (!context)    {        return NULL;    }        //获取xpath对象指针    xmlChar *xml_key = xmlCharStrdup(key);    xmlXPathObjectPtr result = xmlXPathEvalExpression(xml_key, context);    xmlFree(xml_key);    //释放xpath上下文    xmlXPathFreeContext(context);    //    if (!result)    {        return NULL;    }    //结果为空    if (!result || xmlXPathNodeSetIsEmpty(result->nodesetval))    {        return NULL;    }    return result;}//更新结点内容void UpdateXmlNodeValue(xmlDocPtr doc, const char *key, const char *value){    xmlXPathObjectPtr result = GetXPathObject(doc, key);    if (!result)    {        return;    }    xmlNodeSetPtr nodeset = result->nodesetval;    for (int i = 0; i < nodeset->nodeNr; i++)    {        //更新结点值        UpdateNodeValue(nodeset->nodeTab[i], value);    }    xmlXPathFreeObject(result);}//更新结点属性值void UpdateXmlNodeAttr(xmlDocPtr doc, const char *key, const char *attr_name, const char *value){    xmlXPathObjectPtr result = GetXPathObject(doc, key);    if (!result)    {        return;    }        xmlNodeSetPtr nodeset = result->nodesetval;    for (int i = 0; i < nodeset->nodeNr; i++)    {        UpdateAttrValue(nodeset->nodeTab[i], attr_name, value);    }    xmlXPathFreeObject(result);}xmlDocPtr BeginUpdate(const char *xml_path){    xmlInitParser();    xmlDocPtr doc = xmlParseFile(xml_path);    return doc;}void EndUpdate(xmlDocPtr doc, const char *out_path){    xmlSaveFileEnc(out_path, doc, "UTF-8");    xmlFreeDoc(doc);    xmlCleanupParser();}int main(int argc, char** argv){    xmlDocPtr doc = BeginUpdate("test.xml");//    UpdateXmlNodeValue(doc, "//toolbarwindow[@name]", "goodbye");    UpdateXmlNodeValue(doc, "//selectwindow", "goodbye");    UpdateXmlNodeAttr(doc, "//toolbarwindow/rect[@x]", "x","100");    EndUpdate(doc, "out.xml");    return 0;}


//测试例子[test.xml]

<xml><selectwindow>It is a select object window</selectwindow><toolbarwindow name="toolbar" width="200">It is a toolbar.<rect x="4" y="5"/></toolbarwindow ></xml>


 

运行结果[out.xml]:

<?xml version="1.0" encoding="UTF-8"?><xml><selectwindow>goodbye</selectwindow><toolbarwindow name="toolbar" width="200">It is a toolbar.<rect x="100" y="5"/></toolbarwindow></xml>


 

问题:

如果这程序执行这条语句:UpdateXmlNodeValue(doc, "//toolbarwindow[@name]", "goodbye");

结果为:

<?xml version="1.0" encoding="UTF-8"?><xml><selectwindow>goodbye</selectwindow><toolbarwindow name="toolbar" width="200">goodbye</toolbarwindow></xml>

里面的<rect x="4" y="5"/>也被删除了.有兴趣的可以修改这个问题