通过本文主要向大家介绍了rapidxml,rapidxml int,浅谈全过程造价控制,浅谈全过程造价管理,浅谈政府预算管理过程等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
C++解析xml的开源库有很多,在此我就不一一列举了,今天主要说下Rapidxml,我使用这个库也并不是很多,如有错误之处还望大家能够之处,谢谢。
附:
官方链接:http://rapidxml.sourceforge.net/
官方手册:http://rapidxml.sourceforge.net/manual.html
之前有一次用到,碰到了个"坑",当时时间紧迫并未及时查找,今天再次用到这个库,对这样的"坑"不能踩第二次,因此我决定探个究竟。
先写两段示例:
创建xm:
void CreateXml() { rapidxml::xml_document<> doc; auto nodeDecl = doc.allocate_node(rapidxml::node_declaration); nodeDecl->append_attribute(doc.allocate_attribute("version", "1.0")); nodeDecl->append_attribute(doc.allocate_attribute("encoding", "UTF-8")); doc.append_node(nodeDecl);//添加xml声明 auto nodeRoot = doc.allocate_node(rapidxml::node_element, "Root");//创建一个Root节点 nodeRoot->append_node(doc.allocate_node(rapidxml::node_comment, NULL, "编程语言"));//添加一个注释内容到Root,注释没有name 所以第二个参数为NULL auto nodeLangrage = doc.allocate_node(rapidxml::node_element, "language", "This is C language");//创建一个language节点 nodeLangrage->append_attribute(doc.allocate_attribute("name", "C"));//添加一个name属性到language nodeRoot->append_node(nodeLangrage); //添加一个language到Root节点 nodeLangrage = doc.allocate_node(rapidxml::node_element, "language", "This is C++ language");//创建一个language节点 nodeLangrage->append_attribute(doc.allocate_attribute("name", "C++"));//添加一个name属性到language nodeRoot->append_node(nodeLangrage); //添加一个language到Root节点 doc.append_node(nodeRoot);//添加Root节点到Document std::string buffer; rapidxml::print(std::back_inserter(buffer), doc, 0); std::ofstream outFile("language.xml"); outFile << buffer; outFile.close(); }</div>
结果:
<?xml version="1.0" encoding="UTF-8"?> <Root> <!--编程语言--> <language name="C">This is C language</language> <language name="C++">This is C++ language</language> </Root></div>
修改xml:
void MotifyXml() { rapidxml::file<> requestFile("language.xml");//从文件加载xml rapidxml::xml_document<> doc; doc.parse<0>(requestFile.data());//解析xml auto nodeRoot = doc.first_node();//获取第一个节点,也就是Root节点 auto nodeLanguage = nodeRoot->first_node("language");//获取Root下第一个language节点 nodeLanguage->first_attribute("name")->value("Motify C");//修改language节点的name属性为 Motify C std::string buffer; rapidxml::print(std::back_inserter(buffer), doc, 0); std::ofstream outFile("MotifyLanguage.xml"); outFile << buffer; outFile.close(); }</div>
结果:
<Root> <language name="Motify C">This is C language</language> <language name="C++">This is C++ language</language> </Root></div>
由第二个结果得出:
第一个language的name属性确实改成我们所期望的值了,不过不难发现xml的声明和注释都消失了。是怎么回事呢?这个问题也困扰了我一段时间,既然是开源库,那我们跟一下看看他都干了什么,从代码可以看出可疑的地方主要有两处:print和parse,这两个函数均需要提供一个flag,这个flag到底都干了什么呢,从官方给的教程来看 均使用的0,既然最终执行的是print我们就从print开始调试跟踪吧
找到了找到print调用的地方:
template<class OutIt, class Ch> inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0) { return internal::print_node(out, &node, flags, 0); }</div>
继续跟踪:
// 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; }</div>
跟进print_children 发现这实际是个递归,我们继续跟踪
// Print element node template<class OutIt, class Ch> inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) { assert(node->type() == node_element); // Print element name and attributes, if any if (!(flags & print_no_indenting)) ...//省略部分代码 return out; }</div>
我们发现第8行有一个&判断 查看print_no_indenting的定义:
// Printing flags const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.</div>
据此我们就可以分析了,按照开发风格统一的思想,parse也应该有相同的标志定义
省略分析parse流程..
我也顺便去查看了官方文档,确实和我预想的一样,贴一下头文件中对这些标志的描述,详细信息可参考官方文档
// Parsing flags //! Parse flag instructing the parser to not create data nodes. //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. //! Can be combined with other flags by use of | operator. //! <br><br> //! See xml_document::parse() function. const int parse_no_data_nodes = 0x1; //! Parse flag instructing the parser to not use text of first data node as a value of parent element. //! Can be combined with other flags by use of | operator. //! Note that child data nodes of element node take precendence over its value when printing. //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored. //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. //! <br&g