青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++分析研究  
C++
日歷
<2014年3月>
2324252627281
2345678
9101112131415
16171819202122
23242526272829
303112345
統計
  • 隨筆 - 92
  • 文章 - 4
  • 評論 - 4
  • 引用 - 0

導航

常用鏈接

留言簿

隨筆檔案

文章檔案

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

 

  boost.property_tree可以用來解析xml和json文件,我主要用它來解析xml文件,它內部封裝了號稱最快的xml解析器rapid_xml,其解析效率還是很好的。但是在使用過程中卻發現各種不好用,歸納一下不好用的地方有這些:

  獲取不存在的節點時就拋出異常

  獲取屬性值時,要排除屬性和注釋節點,如果沒注意這一點就會拋出異常,讓人摸不著頭腦。

  內存模型有點怪。

  默認不支持中文的解析。解析中文會亂碼。

  ptree獲取子節點

  獲取子節點接口原型為get_child(node_path),這個node_path從當前路徑開始的全路徑,父路徑和子路徑之間通過“.”連接,如“root.sub.child”。需要注意的是get_child獲取的是第一個子節點,如果我們要獲取子節點列表,則要用路徑“root.sub”,這個路徑可以獲取child的列表。如果獲取節點的路徑不存在則會拋出異常,這時,如果不希望拋出異常則可以用get_xxx_optional接口,該接口返回一個optional的結果出來,由外面判斷是否獲取到結果托福答案 www.jamo123.com

  //ptree的optional接口

  auto item = root.get_child_optional("Root.Scenes");

  該接口返回的是一個optional,外面還要判斷該節點是否存在,optional對象通過bool操作符來判斷該對象是否是無效值,通過指針訪問

  符"*"來訪問該對象的實際內容。建議用optional接口訪問xml節點。

  //ptree的optional接口

  auto item = root.get_child_optional("Root.Scenes");

  if(item)

  cout<<"該節點存在"<

  ptree的內存模型

  ptree維護了一個pair的子節點列表,first指向的是該節點的TagName,second指向的才是ptree節點,因此在遍歷ptree子節點時要注意迭代器的含義。

  for (auto& data : root)

  {

  for (auto& item : data.second) //列表元素為pair,要用second繼續遍歷

  {

  cout<

  }

  }

  需要注意的是ptree.first可能是屬性("")也可能是注釋(""),只有非注釋類型的節點才能使用獲取屬性值、子節點等常用接口。

  ptree獲取屬性值

  通過get(attr_name)可以獲取屬性的值,如果想獲取屬性的整形值的話,可以用get("Id"),返回一個整數值。有一點要注意如果ptree.first為""時,是沒有屬性值的,可以通過data()來獲取注釋內容。如果這個ptree.first不為時需要在屬性名稱前面加".",即get(".Id")才能正確獲取屬性值。可以看到獲取屬性值還是比較繁瑣的,在后面要介紹的幫助類中可以簡化屬性值的獲取。如果要獲取節點的值則用get_value()接口,該接口用來獲取節點的值,如節點:2通過get_value()就可以獲取值"2"。

  解析中文的問題

  ptree只能解析窄字符的xml文件,如果xml文件中含有unicode如中文字符,解析出來就是亂碼。解析unicode要用wptree,該類的接口均支持寬字符并且接口和ptree保持一致。要支持中文解析僅僅wptree還不夠,還需要一個unicode轉換器的幫助,該轉換器可以實現寬字符和窄字符的轉換,寬窄的互相轉換函數有很多實現,不過c++11中有更簡單統一的方式實現寬窄字符的轉換。

  c++11中寬窄字符的轉換:

  std::wstring_convert> conv

  (newstd::codecvt("CHS"));

  //寬字符轉為窄字符

  string str = conv.to_bytes(L"你好");

  //窄字符轉為寬字符

  string wstr = conv.from_bytes(str);

  boost.property_tree在解析含中文的xml文件時,需要先將該文件轉換一下。

  boost解決方法:

  #include "boost/program_options/detail/utf8_codecvt_facet.hpp"

  void ParseChn()

  {

  std::wifstream f(fileName);

  std::locale utf8Locale(std::locale(), new boost::program_options::detail::utf8_codecvt_facet());

  f.imbue(utf8Locale); //先轉換一下

  //用wptree去解析

  property_tree::wptree ptree;

  property_tree::read_xml(f, ptree);

  }

  這種方法有個缺點就是要引入boost的libboost_program_options庫,該庫有二十多M,僅僅是為了解決一個中文問題,卻要搞得這么麻煩,有點得不償失。好在c++11提供更簡單的方式,用c++11可以這樣:

  void Init(const wstring& fileName, wptree& ptree)

  {

  std::wifstream f(fileName);

  std::locale utf8Locale(std::locale(), new std::codecvt_utf8);

  f.imbue(utf8Locale); //先轉換一下

  //用wptree去解析

  property_tree::read_xml(f, ptree);

  }

  用c++11就不需要再引入boost的libboost_program_options庫了,很簡單。

  property_tree的幫助類

  property_tree的幫助類解決了前面提到的問題:

  用c++11解決中文解析問題

  簡化屬性的獲取

  增加一些操作接口,比如一些查找接口

  避免拋出異常,全部返回optional對象

  隔離了底層繁瑣的操作接口,提供統一、簡潔的高層接口,使用更加方便。

  下面來看看這個幫助類是如何實現的吧:

  #include

  #include

  using namespace boost;

  using namespace boost::property_tree;

  #include

  #include

  #include

  #include

  using namespace std;

  const wstring XMLATTR = L"";

  const wstring XMLCOMMENT = L"";

  const wstring XMLATTR_DOT = L".";

  const wstring XMLCOMMENT_DOT = L".";

  class ConfigParser

  {

  public:

  ConfigParser() : m_conv(new code_type("CHS"))

  {

  }

  ~ConfigParser()

  {

  }

  void Init(const wstring& fileName, wptree& ptree)

  {

  std::wifstream f(fileName);

  std::locale utf8Locale(std::locale(), new std::codecvt_utf8);

  f.imbue(utf8Locale); //先轉換一下

  wcout.imbue(std::locale("chs")); //初始化cout為中文輸出格式

  //用wptree去解析

  property_tree::read_xml(f, ptree);

  }

  // convert UTF-8 string to wstring

  std::wstring to_wstr(const std::string& str)

  {

  return m_conv.from_bytes(str);

  }

  // convert wstring to UTF-8 string

  std::string to_str(const std::wstring& str)

  {

  return m_conv.to_bytes(str);

  }

  //獲取子節點列表

  auto Descendants(const wptree& root, const wstring& key)->decltype(root.get_child_optional(key))

  {

  return root.get_child_optional(key);

  }

  //根據子節點屬性獲取子節點列表

  template

  vector GetChildsByAttr(const wptree& parant, const wstring& tagName, const wstring& attrName, const T& attrVal)

  {

  vector v;

  for (auto& child : parant)

  {

  if (child.first != tagName)

  continue;

  auto attr = Attribute(child, attrName);

  if (attr&&*attr == attrVal)

  v.push_back(child.second);

  }

  return v;

  }

  //獲取節點的某個屬性值

  template

  optional Attribute(const wptree& node, const wstring& attrName)

  {

  return node.get_optional(XMLATTR_DOT + attrName);

  }

  //獲取節點的某個屬性值,默認為string

  optional Attribute(const wptree& node, const wstring& attrName)

  {

  return Attribute(node, attrName);

  }

  //獲取value_type的某個屬性值

  template

  optional Attribute(const wptree::value_type& pair, const wstring& attrName)

  {

  if (pair.first == XMLATTR)

  return pair.second.get_optional(attrName);

  else if (pair.first == XMLCOMMENT)

  return optional();

  else

  return pair.second.get_optional(XMLATTR_DOT + attrName);

  }

  //獲取value_type的某個屬性值,默認為string

  optional Attribute(const wptree::value_type& pair, const wstring& attrName)

  {

  return Attribute(pair, attrName);

  }

  //根據某個屬性生成一個的multimap

  template>

  multimap MakeMapByAttr(const wptree& root, const wstring& key, const wstring& attrName, F predict = [](wstring& str){return true; })

  {

  multimap resultMap;

  auto list = Descendants(root, key);

  if (!list)

  return resultMap;

  for (auto& item : *list)

  {

  auto attr = Attribute(item, attrName);

  if (attr&&predict(*attr))

  resultMap.insert(std::make_pair(*attr, item.second));

  }

  return resultMap;

  }

  private:

  using code_type = std::codecvt;

  std::wstring_convert m_conv;

  };

  View Code

  測試文件test.xml和測試代碼:

  void Test()

  {

  wptree pt; pt.get_value()

  ConfigParser parser;

  parser.Init(L"test1.xml", pt); //解決中文問題,要轉換為unicode解析

  auto scenes = parser.Descendants(pt, L"Root.Scenes"); //返回的是optional

  if (!scenes)

  return;

  for (auto& scene : *scenes)

  {

  auto s = parser.Attribute(scene, L"Name"); //獲取Name屬性,返回的是optional

  if (s)

  {

  wcout << *s << endl;

  }

  auto dataList = parser.Descendants(scene.second, L"DataSource"); //獲取第一個子節點

  if (!dataList)

  continue;

  for (auto& data : *dataList)

  {

  for (auto& item : data.second)

  {

  auto id = parser.Attribute(item, L"Id");

  auto fileName = parser.Attribute(item, L"FileName");

  if (id)

  {

  wcout << *id << L" " << *fileName << endl; //打印id和filename

  }

  }

  }

  }

  }

  測試結果:


  可以看到通過幫助類,無需使用原生接口就可以很方便的實現節點的訪問與操作。使用者不必關注內部細節,根據統一而簡潔的接口就可以操作xml文件了。

  一點題外話,基于這個幫助類再結合linq to object可以輕松的實現linq to xml:

  //獲取子節點SubNode的屬性ID的值為0x10000D的項并打印出該項的Type屬性

  from(node.Descendants("Root.SubNode")).where([](XNode& node)

  {

  auto s = node.Attribute("ID");

  return s&&*s == "0x10000D";

  }).for_each([](XNode& node)

  {

  auto s = node.Attribute("Type");

  if (s)

  cout << *s << endl;

  });

posted on 2014-03-11 16:27 HAOSOLA 閱讀(5148) 評論(0)  編輯 收藏 引用
 
Copyright © HAOSOLA Powered by: 博客園 模板提供:滬江博客
PK10開獎 PK10開獎
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产日韩精品入口| 欧美成人a视频| 狠狠色综合日日| 国产精品一区视频| 国产精品毛片大码女人| 欧美日韩亚洲高清| 国产精品一区二区你懂的| 国产精品自拍视频| 激情亚洲网站| 亚洲六月丁香色婷婷综合久久| 亚洲人成高清| 亚洲男女自偷自拍| 老司机精品视频网站| 麻豆精品一区二区av白丝在线| 亚洲黄色免费网站| 亚洲高清在线视频| 一区二区久久久久| 久久精品国产免费观看| 欧美成va人片在线观看| 国产精品三上| 亚洲国产欧美在线| 免费观看在线综合| 欧美色中文字幕| 国模精品一区二区三区色天香| 亚洲免费电影在线| 久久精品国产亚洲一区二区| 亚洲国产一区二区视频| 亚洲一区免费| 欧美精品久久久久久久免费观看| 国产精品久久久久久影视| 亚洲区免费影片| 欧美亚洲免费电影| 亚洲激情在线观看| 欧美资源在线观看| 欧美性事免费在线观看| 亚洲激情二区| 蜜臀久久99精品久久久画质超高清| 99亚洲精品| 美女成人午夜| 揄拍成人国产精品视频| 亚洲欧美另类中文字幕| 91久久精品美女高潮| 欧美在线免费一级片| 欧美午夜视频在线| 一本久道久久综合婷婷鲸鱼| 欧美国产日本高清在线| 久久久蜜桃精品| 国产一区日韩欧美| 久久成人精品视频| 午夜欧美不卡精品aaaaa| 欧美四级在线| 中文国产成人精品| 日韩视频在线一区二区三区| 免费在线看一区| 一区二区三区在线高清| 久久久久成人网| 久久精品国产精品亚洲综合| 欧美在线日韩在线| 亚洲图片欧洲图片av| 欧美香蕉视频| 亚洲自啪免费| 亚洲视频免费在线| 国产精品高潮视频| 亚洲欧美日韩人成在线播放| 亚洲精品欧美在线| 国产精品国产福利国产秒拍| 午夜在线观看免费一区| 亚洲影院免费观看| 国产亚洲福利| 麻豆成人91精品二区三区| 久久久亚洲成人| 亚洲高清在线观看| 最新成人在线| 欧美精品一区二区蜜臀亚洲| 一区二区三欧美| 亚洲午夜一区二区| 国产一区二区无遮挡| 久久不射电影网| 久久久噜噜噜| aa国产精品| 亚洲欧美日韩一区二区三区在线| 久久久久久9| 亚洲黄色三级| 99re热这里只有精品视频| 欧美午夜精品久久久久久浪潮| 性欧美8khd高清极品| 久久综合电影一区| 中文日韩在线视频| 欧美在线一级视频| 亚洲免费观看视频| 亚洲在线中文字幕| 激情欧美一区二区| 日韩一区二区福利| 在线观看av不卡| 一区二区三区四区五区精品视频 | 亚洲国产成人午夜在线一区| 欧美伦理视频网站| 久久精品中文字幕免费mv| 欧美韩日视频| 久久精品欧美| 欧美日韩在线第一页| 久久综合婷婷| 国产精品www994| 欧美成人综合网站| 国产精品一区二区视频| 欧美韩日一区二区三区| 国产精品久久久久久久一区探花| 另类专区欧美制服同性| 欧美午夜不卡视频| 亚洲成色777777在线观看影院| 国产精品久久久久影院色老大 | 欧美一区二区三区啪啪| 日韩一级黄色av| 久久经典综合| 亚洲欧美在线免费观看| 欧美高清在线观看| 欧美成人国产| 好吊一区二区三区| 香蕉久久一区二区不卡无毒影院| 99成人在线| 欧美成年人网| 免费av成人在线| 国产一区二区三区四区hd| 亚洲一区二区毛片| 亚洲一区二区av电影| 欧美成人午夜| 欧美激情久久久久久| 黄色成人av网站| 午夜日韩福利| 久久久久久久精| 国产女人精品视频| 小处雏高清一区二区三区| 欧美一级专区免费大片| 国产美女精品免费电影| 亚洲综合色网站| 久久成人资源| 国产一区二区精品久久| 性做久久久久久免费观看欧美| 亚洲无限乱码一二三四麻| 欧美午夜宅男影院| 一区二区三区四区蜜桃| 午夜精品福利一区二区三区av| 国产精品国内视频| 国产精品呻吟| 久久在线观看视频| 久久久综合精品| 极品中文字幕一区| 久久人人爽人人| 免费短视频成人日韩| 国产一区二区精品| 久久久久久精| 亚洲福利在线视频| 一区二区av| 国产精品三级久久久久久电影| 亚洲女爱视频在线| 久久综合婷婷| 夜夜嗨网站十八久久| 国产精品久久久久久影院8一贰佰 国产精品久久久久久影视 | 国产久一道中文一区| 性感少妇一区| 欧美国产日韩免费| 亚洲视频中文| 国产欧美69| 老色鬼久久亚洲一区二区| 亚洲精品国产拍免费91在线| 亚洲一区视频在线| 国产亚洲精品一区二555| 另类春色校园亚洲| 日韩午夜激情av| 性xx色xx综合久久久xx| 伊人久久婷婷| 国产精品黄页免费高清在线观看| 亚洲欧美视频在线观看视频| 免费欧美电影| 亚洲一区在线免费| 在线观看日韩国产| 国产精品jvid在线观看蜜臀| 久久激情视频免费观看| 亚洲精品色图| 久久久国产视频91| 亚洲一区二区三区中文字幕在线| 国产拍揄自揄精品视频麻豆| 久久综合伊人77777蜜臀| 亚洲一区二区三区精品视频| 免费在线播放第一区高清av| 亚洲免费视频网站| 亚洲欧洲精品成人久久奇米网| 国产精品自拍小视频| 欧美激情一区二区三区全黄| 久久国产欧美日韩精品| 中文在线资源观看视频网站免费不卡| 毛片基地黄久久久久久天堂| 欧美一级在线播放| 亚洲直播在线一区| 一区二区三区国产盗摄| 亚洲日本成人网| 在线免费观看视频一区| 国产一区二区三区四区hd| 国产精品实拍| 国产精品日韩欧美综合 |