加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 创业 > 经验 > 正文

浅谈使用Rapidxml 库遇到的问题和分析过程(分享)

发布时间:2021-01-09 18:20:21 所属栏目:经验 来源:网络整理
导读:C++解析xml的开源库有很多,在此我就不一一列举了,今天主要说下Rapidxml,我使用这个库也并不是很多,如有错误之处还望大家能够之处,谢谢。 附: 官方链接:http://rapidxml.sourceforge.net/ 官方手册:http://rapidxml.sourceforge.net/manual.html 之前
副标题[/!--empirenews.page--]

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,"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();
}

结果:

 <?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>

修改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),0);
  std::ofstream outFile("MotifyLanguage.xml");
  outFile << buffer;
  outFile.close();
}

结果:

 <Root>
   <language name="Motify C">This is C language</language>
   <language name="C++">This is C++ language</language>
 </Root>

由第二个结果得出:

第一个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);
   }

继续跟踪:

// 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,indent);
        break;

      // Element
      case node_element:
        out = print_element_node(out,indent);
        break;
      
      // Data
      case node_data:
        out = print_data_node(out,indent);
        break;
      
      // CDATA
      case node_cdata:
        out = print_cdata_node(out,indent);
        break;

      // Declaration
      case node_declaration:
        out = print_declaration_node(out,indent);
        break;

      // Comment
      case node_comment:
        out = print_comment_node(out,indent);
        break;
      
      // Doctype
      case node_doctype:
        out = print_doctype_node(out,indent);
        break;

      // Pi
      case node_pi:
        out = print_pi_node(out,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;
    }

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读