亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

淺談使用Rapidxml 庫遇到的問題和分析過程(分享)

2020-01-26 14:08:25
字體:
來源:轉載
供稿:網友

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

結果:

 <?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), doc, 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, 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;    }

跟進print_children 發現這實際是個遞歸,我們繼續跟蹤

// Print element nodetemplate<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;}

我們發現第8行有一個&判斷 查看print_no_indenting的定義:

// Printing flagsconst int print_no_indenting = 0x1;  //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.

據此我們就可以分析了,按照開發風格統一的思想,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><br>  //! See xml_document::parse() function.  const int parse_no_element_values = 0x2;    //! Parse flag instructing the parser to not place zero terminators after strings in the source text.  //! By default zero terminators are placed, modifying source text.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_no_string_terminators = 0x4;    //! Parse flag instructing the parser to not translate entities in the source text.  //! By default entities are translated, modifying source text.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_no_entity_translation = 0x8;    //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.  //! By default, UTF-8 handling is enabled.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_no_utf8 = 0x10;    //! Parse flag instructing the parser to create XML declaration node.  //! By default, declaration node is not created.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_declaration_node = 0x20;    //! Parse flag instructing the parser to create comments nodes.  //! By default, comment nodes are not created.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_comment_nodes = 0x40;    //! Parse flag instructing the parser to create DOCTYPE node.  //! By default, doctype node is not created.  //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_doctype_node = 0x80;    //! Parse flag instructing the parser to create PI nodes.  //! By default, PI nodes are not created.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_pi_nodes = 0x100;    //! Parse flag instructing the parser to validate closing tag names.   //! If not set, name inside closing tag is irrelevant to the parser.  //! By default, closing tags are not validated.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_validate_closing_tags = 0x200;    //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.  //! By default, whitespace is not trimmed.   //! This flag does not cause the parser to modify source text.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_trim_whitespace = 0x400;  //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.  //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.  //! By default, whitespace is not normalized.   //! If this flag is specified, source text will be modified.  //! Can be combined with other flags by use of | operator.  //! <br><br>  //! See xml_document::parse() function.  const int parse_normalize_whitespace = 0x800;  // Compound flags    //! Parse flags which represent default behaviour of the parser.   //! This is always equal to 0, so that all other flags can be simply ored together.  //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.  //! This also means that meaning of each flag is a <i>negation</i> of the default setting.   //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,  //! and using the flag will disable it.  //! <br><br>  //! See xml_document::parse() function.  const int parse_default = 0;    //! A combination of parse flags that forbids any modifications of the source text.   //! This also results in faster parsing. However, note that the following will occur:  //! <ul>  //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>  //! <li>entities will not be translated</li>  //! <li>whitespace will not be normalized</li>  //! </ul>  //! See xml_document::parse() function.  const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;    //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.  //! <br><br>  //! See xml_document::parse() function.  const int parse_fastest = parse_non_destructive | parse_no_data_nodes;    //! A combination of parse flags resulting in largest amount of data being extracted.   //! This usually results in slowest parsing.  //! <br><br>  //! See xml_document::parse() function.  const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;

根據以上提供的信息我們改下之前的源代碼:

 doc.parse<0>(requestFile.data());//解析xml auto nodeRoot = doc.first_node("");//獲取第一個節點,也就是Root節點 

改為

 doc.parse<rapidxml::parse_declaration_node | rapidxml::parse_comment_nodes | rapidxml::parse_non_destructive>(requestFile.data());//解析xml auto nodeRoot = doc.first_node("Root");//獲取第一個節點,也就是Root節點

這里解釋一下,parse加入了三個標志,分別是告訴解析器創建聲明節點、告訴解析器創建注釋節點、和不希望解析器修改傳進去的數據,第二句是當有xml的聲明時,默認的first_node并不是我們期望的Root節點,因此通過傳節點名來找到我們需要的節點。

注:

1、這個庫在append的時候并不去判斷添加項(節點、屬性等)是否存在

2、循環遍歷時對項(節點、屬性等)進行修改會導致迭代失效

總結:用別人寫的庫,總會有些意想不到的問題,至今我只遇到了這些問題,如果還有其它問題歡迎補充,順便解釋下"坑"并不一定是用的開源庫有問題,更多的時候可能是還沒有熟練的去使用這個工具。

感謝rapidxml的作者,為我們提供一個如此高效便利的工具。

以上這篇淺談使用Rapidxml 庫遇到的問題和分析過程(分享)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人免费在线视频网址| 黑人巨大精品欧美一区二区| 国产aaa精品| 欧美成人激情在线| 亚洲国产成人久久综合一区| 亚洲人成五月天| 国产小视频国产精品| 国产午夜精品视频| 日韩高清电影免费观看完整版| 91黑丝高跟在线| 国产精品私拍pans大尺度在线| 国产精品羞羞答答| 亚洲老头老太hd| 91麻豆国产语对白在线观看| 国产精品一区二区久久久| 欧美日韩精品在线播放| 性欧美视频videos6一9| 亚洲一区二区精品| 亚洲精品电影在线| 中文字幕久久亚洲| 欧美激情亚洲一区| 亚洲日韩欧美视频| 亚洲电影中文字幕| 亚洲激情在线观看| 欧洲成人在线视频| 亚洲精品suv精品一区二区| 日韩精品视频在线观看免费| 中文字幕国产日韩| 91夜夜未满十八勿入爽爽影院| 欧美电影免费在线观看| 综合激情国产一区| 欧美裸体xxxx极品少妇软件| 日韩欧美成人免费视频| 日韩电影大片中文字幕| 亚洲成色777777在线观看影院| 91情侣偷在线精品国产| 国产小视频91| 中文字幕日韩在线观看| 亚洲精品资源在线| 精品国内自产拍在线观看| 日韩成人在线电影网| 色诱女教师一区二区三区| 成人a视频在线观看| 国产精品日韩在线| 中文字幕亚洲自拍| 日韩hd视频在线观看| 在线播放日韩欧美| 欧美夫妻性生活xx| 亚洲网站在线播放| 亚洲一区二区三| 精品久久国产精品| 国产精品一区二区三区久久| 欧美老肥婆性猛交视频| 亚洲美女视频网站| 亚洲女同精品视频| 欧美精品在线免费| 欧美日韩一区二区精品| 青青久久aⅴ北条麻妃| 成人伊人精品色xxxx视频| 亚洲永久免费观看| 成人黄色av网| 这里只有精品视频在线| 亚洲一区二区三区视频| 欧美大片大片在线播放| 91沈先生在线观看| 97在线看福利| 亚洲视频欧洲视频| 亚洲福利视频网| 亚洲视频国产视频| 欧美性理论片在线观看片免费| 欧美精品久久久久久久久久| 91精品免费视频| 91老司机在线| 一区二区亚洲欧洲国产日韩| 国产精品美乳一区二区免费| 久久亚洲精品成人| 欧美黑人巨大精品一区二区| 久久精品2019中文字幕| 欧美一级视频一区二区| 另类图片亚洲另类| 色天天综合狠狠色| 亚洲精品按摩视频| 国产欧美最新羞羞视频在线观看| 57pao成人永久免费视频| 精品国产999| 这里只有精品在线播放| 欧美高清第一页| 美女视频久久黄| 亚洲国产成人91精品| 久久琪琪电影院| 成人精品一区二区三区电影黑人| 成人免费视频网址| 日韩欧美成人免费视频| www国产91| 久久天堂av综合合色| 日韩免费av在线| 国产综合在线观看视频| 亚洲国产中文字幕在线观看| 日韩欧美亚洲成人| 久久精品99无色码中文字幕| 亚洲欧美日韩中文在线制服| 国产日本欧美视频| 亚洲视频日韩精品| 亚洲欧美国产高清va在线播| 中文字幕日韩精品在线观看| 在线视频中文亚洲| 一个人www欧美| 91国偷自产一区二区三区的观看方式| 91亚洲精品视频| 亚洲欧美在线一区二区| 68精品国产免费久久久久久婷婷| 久久精品视频中文字幕| 91精品中文在线| 91在线精品播放| 国产成人精彩在线视频九色| 日韩在线观看精品| 精品久久久91| 亚洲国产日韩一区| 最近2019免费中文字幕视频三| 欧美裸体xxxx极品少妇| 琪琪亚洲精品午夜在线| 亚洲精品电影在线观看| 成人在线小视频| 色系列之999| 亚洲人在线视频| 亚洲xxxx做受欧美| 色吧影院999| 97高清免费视频| 国产精品久久久久99| 亚洲美腿欧美激情另类| 国产一区二区三区18| www.日韩欧美| 日韩欧美在线视频日韩欧美在线视频| 亚洲国产天堂久久综合网| 亚洲国产成人一区| 欧美在线一级va免费观看| 日韩中文有码在线视频| 激情懂色av一区av二区av| 高跟丝袜一区二区三区| 欧美国产精品va在线观看| 精品久久久久久国产91| 26uuu另类亚洲欧美日本一| 川上优av一区二区线观看| 成人性生交大片免费观看嘿嘿视频| 2019中文字幕在线| 91国内在线视频| 亚洲成人亚洲激情| 亚洲精品视频二区| 91精品国产91久久久久| 亚洲四色影视在线观看| 欧美激情一区二区三区久久久| 欧美日韩国产色视频| 久久精品成人一区二区三区| 亚洲精品久久久久久久久| 亚洲国产日韩欧美在线图片| 欧美国产乱视频| 久久在线免费观看视频| 国产精品9999| 中文字幕一区电影| 日韩中文字幕在线播放| 日韩美女免费观看| 久久艹在线视频| 久久久之久亚州精品露出| 亚洲欧美中文字幕在线一区|