场景:
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"/>也被删除了.有兴趣的可以修改这个问题