一、写xml 文件
- #include <iostream>
- #include "rapidxml/rapidxml.hpp"
- #include "rapidxml/rapidxml_utils.hpp"
- #include "rapidxml/rapidxml_print.hpp"
- using namespace rapidxml;
- int main()
- {
- xml_document<> doc;
- xml_node<>* rot = doc.allocate_node(rapidxml::node_pi,doc.allocate_string("xml version='1.0' encoding='utf-8'"));
- doc.append_node(rot);
- xml_node<>* node = doc.allocate_node(node_element,"config","information");
- xml_node<>* color = doc.allocate_node(node_element,"color",NULL);
- doc.append_node(node);
- node->append_node(color);
- color->append_node(doc.allocate_node(node_element,"red","0.1"));
- color->append_node(doc.allocate_node(node_element,"green","0.1"));
- color->append_node(doc.allocate_node(node_element,"blue","0.1"));
- color->append_node(doc.allocate_node(node_element,"alpha","1.0"));
- xml_node<>* size = doc.allocate_node(node_element,"size",NULL);
- size->append_node(doc.allocate_node(node_element,"x","640"));
- size->append_node(doc.allocate_node(node_element,"y","480"));
- node->append_node(size);
- xml_node<>* mode = doc.allocate_node(rapidxml::node_element,"mode","screen mode");
- mode->append_attribute(doc.allocate_attribute("fullscreen","false"));
- node->append_node(mode);
- std::string text;
- rapidxml::print(std::back_inserter(text), doc, 0);
- std::cout<<text<<std::endl;
- std::ofstream out("config.xml");
- out << doc;
- system("PAUSE");
- return EXIT_SUCCESS;
- }
生成的xml如下
- <?xml version="1.0" encoding="utf-8" ?>
- - <config>
- - <color>
- <red>0.1</red>
- <green>0.1</green>
- <blue>0.1</blue>
- <alpha>1.0</alpha>
- </color>
- - <size>
- <x>640</x>
- <y>480</y>
- </size>
- <mode fullscreen="false">screen mode</mode>
- </config>
这里需要注意的是:rapidxml为了追求性能,减少内存拷贝,就尽可能的通过指针(内存地址)来访问用户的变量;这就对用户提出了要求:必须保证变量的生存周期,如果变量被销毁了,rapidxml就会访问无效的内存地址,引发不可控的后果。
可见下例:
rapidxml::xml_document<> doc;
void addNode(std::string value)
{
rapidxml::xml_node<>* root = doc.allocate_node(rapidxml::node_element, "unregister_context");
doc.append_node(root);
root->append_node(doc.allocate_node(rapidxml::node_element, "who_register", value.c_str()));
}
这样插入是有问题的,value是临时变量,函数执行完之后就被释放了,正确的方法如下:
rapidxml::xml_document<> doc;
void addNode(std::string value)
{
rapidxml::xml_node<>* root = doc.allocate_node(rapidxml::node_element, "unregister_context");
doc.append_node(root);
root->append_node(doc.allocate_node(rapidxml::node_element, "who_register", doc.allocate_string(value.c_str())));
}
待插入的值"变量value"是作为参数传递进来的,是临时变量。rapidxml为了追求极致性能,在append_node()函数中是直接通过指针来访问value变量的,并没有进行内存拷贝--因此rapidxml在这里提出了一个隐晦的前提条件:在xml对象doc的生命周期内,必须保证"变量value"能够被正常访问。
写文件例子2:
- #include <string>
- #include <iostream>
- #include <fstream>
- #include "rapidxml/rapidxml.hpp"
- #include "rapidxml/rapidxml_utils.hpp"
- #include "rapidxml/rapidxml_print.hpp"
- using namespace rapidxml;
- using namespace std;
- int main(int argc, char* argv[])
- {
- xml_document<> doc; //是解析器
- char a[] = "<top>"//如果单独传, 就不能加上xml的头部信息,
- //否则会报错
- "<name>tangqiang</name>"
- "<age>22</age>"
- "</top>";
- char* p = a;
- doc.parse<0>(p);
- xml_node<>* node = doc.first_node();//去顶级结点
- cout << (node->name())<< endl;
- node = node->first_node();
- while (node) {
- cout << node->name() << node->value() << endl;//name() value()返回的字符串不会去掉首尾的空白字符
- node = node->next_sibling();
- }
- ofstream out("test.xml");//ofstream 默认时,如果文件存在则会覆盖原来的内容,不存在则会新建
- out << doc;//doc 这样输出时在目标文件中不会有xml 头信息---<?xml version='1.0' encoding='utf-8' >
- out.close();
- system("pause");
- return 0;
- }
生成的xml如下
- <top>
- <name>tangqiang</name>
- <age>22</age>
- </top>
二、读取xml文件
- #include <iostream>
- #include "rapidxml/rapidxml.hpp"
- #include "rapidxml/rapidxml_utils.hpp"
- #include "rapidxml/rapidxml_print.hpp"
- using namespace rapidxml;
- int main()
- {
- file<> fdoc("config.xml");
- std::cout<<fdoc.data()<<std::endl;
- xml_document<> doc;
- doc.parse<0>(fdoc.data());
- std::cout<<doc.name()<<std::endl;
- //! 获取根节点
- xml_node<>* root = doc.first_node();
- std::cout<<root->name()<<std::endl;
- //! 获取根节点第一个节点
- xml_node<>* node1 = root->first_node();
- std::cout<<node1->name()<<std::endl;
- xml_node<>* node11 = node1->first_node();
- std::cout<<node11->name()<<std::endl;
- std::cout<<node11->value()<<std::endl;
- //! 添加之后再次保存
- //需要说明的是rapidxml明显有一个bug
- //那就是append_node(doc.allocate_node(node_element,"h","0"));的时候并不考虑该对象是否存在!
- xml_node<>* size = root->first_node("size");
- size->append_node(doc.allocate_node(node_element,"w","0"));
- size->append_node(doc.allocate_node(node_element,"h","0"));
- std::string text;
- rapidxml::print(std::back_inserter(text),doc,0);
- std::cout<<text<<std::endl;
- std::ofstream out("config.xml");
- out << doc;
- system("PAUSE");
- return EXIT_SUCCESS;
- }
生成的xml为
- <config>
- <color>
- <red>0.1</red>
- <green>0.1</green>
- <blue>0.1</blue>
- <alpha>1.0</alpha>
- </color>
- <size>
- <x>640</x>
- <y>480</y>
- <w>0</w>
- <h>0</h>
- </size>
- <mode fullscreen="false">screen mode</mode>
- </config>
三、删除节点
- #include "rapidxml/rapidxml.hpp"
- #include "rapidxml/rapidxml_utils.hpp"
- #include "rapidxml/rapidxml_print.hpp"
- #include<iostream>
- using namespace rapidxml;
- int main()
- {
- file<> fdoc("config.xml");
- xml_document<> doc;
- doc.parse<0>(fdoc.data());
- std::string text;
- rapidxml::print(std::back_inserter(text), doc, 0);
- std::cout<<text<<std::endl;
- xml_node<>* root = doc.first_node();
- xml_node<>* sec = root->first_node();
- root->remove_node(sec); //移除根节点下的sec结点(包括该结点下所有结点)
- text="删除一个节点\r\n";
- rapidxml::print(std::back_inserter(text), doc, 0);
- std::cout<<text<<std::endl;
- root->remove_all_nodes(); //移除根节点下所有结点
- text="删除所有节点\r\n";
- rapidxml::print(std::back_inserter(text), doc, 0);
- std::cout<<text<<std::endl;
- std::ofstream out("test.xml");
- out<<doc;
- system("pause");
- return 0;
- }
输出信息如下:
- <config>
- <color>
- <red>0.1</red>
- <green>0.1</green>
- <blue>0.1</blue>
- <alpha>1.0</alpha>
- </color>
- <size>
- <x>640</x>
- <y>480</y>
- <w>0</w>
- <h>0</h>
- </size>
- <mode fullscreen="false">screen mode</mode>
- </config>
- 删除一个节点
- <config>
- <size>
- <x>640</x>
- <y>480</y>
- <w>0</w>
- <h>0</h>
- </size>
- <mode fullscreen="false">screen mode</mode>
- </config>
- 删除所有节点
- <config/>
四、编辑节点信息
暂时找到的编辑方法就是先删除再增加
- #include "rapidxml/rapidxml.hpp"
- #include "rapidxml/rapidxml_utils.hpp"
- #include "rapidxml/rapidxml_print.hpp"
- #include<iostream>
- using namespace rapidxml;
- int main()
- {
- file<> fdoc("config.xml");
- std::cout<<fdoc.data()<<std::endl;
- xml_document<> doc;
- doc.parse<0>(fdoc.data());
- std::cout<<doc.name()<<std::endl;
- //! 获取根节点
- xml_node<>* root = doc.first_node();
- xml_node<>* delnode = root->first_node("color");
- root->remove_node(delnode);//先删除address节点
- //
- xml_node<>* lnode = root->first_node("size");//找到post节点
- xml_node<>* mynode=doc.allocate_node(node_element,"address","河北");
- root->insert_node(lnode,mynode);
- std::string text;
- rapidxml::print(std::back_inserter(text),doc,0);
- std::cout<<text<<std::endl;
- std::ofstream out("version.xml");
- out << doc;
- system("pause");
- return 0;
- }
输出如下:
- <config>
- <color>
- <red>0.1</red>
- <green>0.1</green>
- <blue>0.1</blue>
- <alpha>1.0</alpha>
- </color>
- <size>
- <x>640</x>
- <y>480</y>
- <w>0</w>
- <h>0</h>
- </size>
- <mode fullscreen="false">screen mode</mode>
- </config>
- <config>
- <address>河北</address>
- <size>
- <x>640</x>
- <y>480</y>
- <w>0</w>
- <h>0</h>
- </size>
- <mode fullscreen="false">screen mode</mode>
- </config>
五、遍历所有节点
- for(rapidxml::xml_node<char> * node = parent_node->first_node("node name");
- node != NULL;
- node = node->next_sibling())
- {
- ...
- }
六、遍历所有属性
- for(rapidxml::xml_attribute<char> * attr = node->first_attribute("node name");
- attr != NULL;
- attr = attr->next_attribute())
- {
- char * value = attr->value();
- }
七、gcc使用-std=gnu++0x
编译rapidxml时会报错,错误信息大概如下
...rapidxml_print.hpp:120:23: error:
call to function 'print_element_node' thatis neither visible in the
template definition nor found byargument-dependent lookup
out = print_element_node(out, node, flags,indent);
^
...rapidxml_print.hpp:242:22: note:
'print_element_node' should be declaredprior to the call site or in
namespace 'rapidxml'
inline OutIt print_element_node(OutIt out,const xml_node<Ch> ...
经查,原来print_node()函数被其他函数调用,但在却未定义(在被调用函数后定义了),所以解决方法为把print_node()函数移到print_children(), print_element_node() 等函数的后面。在原定义处就留一个函数声明就行。
具体diff文件如下。
- Index: rapidxml_print.hpp
- ===================================================================
- --- rapidxml_print.hpp (revision 2025)
- +++ rapidxml_print.hpp (revision 2080)
- @@ -101,68 +101,9 @@
- ///
- // Internal printing operations
- -
- - // Print node
- +
- template<class OutIt, class Ch>
- - inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
- - {
- - // Print proper node type
- - switch (node->type())
- - {
- -
- - // Document
- - case node_document:
- - out = print_children(out, node, flags, indent);
- - break;
- -
- - // Element
- - case node_element:
- - out = print_element_node(out, node, flags, indent);
- - break;
- -
- - // Data
- - case node_data:
- - out = print_data_node(out, node, flags, indent);
- - break;
- -
- - // CDATA
- - case node_cdata:
- - out = print_cdata_node(out, node, flags, indent);
- - break;
- -
- - // Declaration
- - case node_declaration:
- - out = print_declaration_node(out, node, flags, indent);
- - break;
- -
- - // Comment
- - case node_comment:
- - out = print_comment_node(out, node, flags, indent);
- - break;
- -
- - // Doctype
- - case node_doctype:
- - out = print_doctype_node(out, node, flags, indent);
- - break;
- -
- - // Pi
- - case node_pi:
- - out = print_pi_node(out, node, flags, indent);
- - break;
- -
- - // Unknown
- - default:
- - assert(0);
- - break;
- - }
- -
- - // If indenting not disabled, add line break after node
- - if (!(flags & print_no_indenting))
- - *out = Ch('\n'), ++out;
- -
- - // Return modified iterator
- - return out;
- - }
- + inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
- // Print children of the node
- template<class OutIt, class Ch>
- @@ -372,7 +313,69 @@
- *out = Ch('>'), ++out;
- return out;
- }
- +
- + // Print node
- + template<class OutIt, class Ch>
- + inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
- + {
- + // Print proper node type
- + switch (node->type())
- + {
- + // Document
- + case node_document:
- + out = print_children(out, node, flags, indent);
- + break;
- +
- + // Element
- + case node_element:
- + out = print_element_node(out, node, flags, indent);
- + break;
- +
- + // Data
- + case node_data:
- + out = print_data_node(out, node, flags, indent);
- + break;
- +
- + // CDATA
- + case node_cdata:
- + out = print_cdata_node(out, node, flags, indent);
- + break;
- +
- + // Declaration
- + case node_declaration:
- + out = print_declaration_node(out, node, flags, indent);
- + break;
- +
- + // Comment
- + case node_comment:
- + out = print_comment_node(out, node, flags, indent);
- + break;
- +
- + // Doctype
- + case node_doctype:
- + out = print_doctype_node(out, node, flags, indent);
- + break;
- +
- + // Pi
- + case node_pi:
- + out = print_pi_node(out, node, flags, indent);
- + break;
- +
- + // Unknown
- + default:
- + assert(0);
- + break;
- + }
- +
- + // If indenting not disabled, add line break after node
- + if (!(flags & print_no_indenting))
- + *out = Ch('\n'), ++out;
- +
- + // Return modified iterator
- + return out;
- + }
- +
- }
- //! \endcond