2017-11-30 23 views
1

私は以下のxmlデータを持っています。私はboost xml parserを解析したいと思います。ブーストとxmlの解析

<?xml version="1.0" encoding="UTF-8"?> 
<applications> 
    <application> 
      <id>1</id> 
      <platform>linux-x64</platform> 
      <version>2.4</version> 
    </application> 
    <application> 
      <id>2</id> 
      <platform>windows</platform> 
      <version>2.5</version> 
    </application> 
    <application> 
      <id>3</id> 
      <platform>linux</platform> 
      <version>2.6</version> 
    </application> 
</applications> 

私は以下のブーストコードを書いていますが、「アプリケーション」の最初の子のみを読み込み、他の2人の子を読み取ることはできません。毎回内部ループが最初の子のデータを取得します。

boost::property_tree::ptree pt; 
boost::property_tree::read_xml(sModel, pt); // sModel is filename which contains above xml data 

BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("applications")) 
{ 
    std::string key = v.first.data();  
    std::string Id, platform, version; 

    if (key == std::string("application")) 
    { 
     BOOST_FOREACH(boost::property_tree::ptree::value_type &v_, pt.get_child("applications.application")) 
     { 
      std::string app_key = v_.first.data(); 
      std::string app_value = v_.second.data(); 

      if (app_key == std::string("id")) 
       pkgId = app_value; 
      else if (app_key == std::string("platform")) 
       platform = app_value; 
      else if (app_key == std::string("version")) 
       version = app_value; 
     } 
    } 
} 

ここで、私はプラットフォームを "linux-x64"としています。 誰かがこのboost xmlを通してすべての子供を読む方法を指導できますか?

ありがとうございました。

+1

ブーストXMLパーサが本当にありません。 PropertyTreeには、変更されたRapidXMLパーサーを介してXMLから読み込むための基本的なサポートがいくつかありますが、ほとんどのXMLはサポートされていません。また、データにアクセスする際にはわかります。 –

+0

@SebastianRedl福音を伝えてくれてありがとう。私はそれが常識になってうれしいです。私はデータアクセスがiffyであるとは言いません。実際、プロパティへのアクセスにはかなりいいですね。 (例:[回避ループフレージー](https://stackoverflow.com/questions/47013164/boostproperty-tree-parsing-of-complex-xml-strucure/47019176#47019176)と[translators](https:// stackoverflow。 com/a/43769414/85371))。 – sehe

答えて

2

get_child(および他のすべてのパスベースのアクセス機能)は、複数の同一のキーを処理することであまりよくありません。指定されたキーを持つ最初の子を選択し、それを返します。他の子はすべて無視します。

手に入れたいノードをすでに持っているので、get_childは必要ありません。

pt.get_child("applications")は、ptreeです。それを繰り返すとptree::value_typeとなり、それはstd::pair<std::string, ptree>です。

最初の奇妙なことは、それから、この行です:

std::string key = v.first.data(); 

あなたがここに呼んでいるdata()機能がstd::string::data、ないptree::dataです。あなたがここで明示的にstd::stringを構築する必要はありません

if (key == std::string("application")) 

:あなただけ

std::string key = v.first; 

次の奇妙なことが比較で書くことができます。実際には、std::stringにCスタイルの文字列の比較演算子がある場合は、文字列バッファを割り当ててそこに文字列をコピーする必要があるため、これを悲観的にします。

次に、pt.get_child("applications.application")以上の反復子ですが、この参照を行う必要はありません。v.secondは既に必要なツリーです。

さらに、子を何度も繰り返す必要はなく、ルックアップ関数を使用して必要なものを取得することができます。

std::string pkgId = v.second.get("id", ""); 

ので、合計する、これは私が書くでしょうコードです:

boost::property_tree::ptree pt; 
boost::property_tree::read_xml(sModel, pt); 

BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("applications")) 
{ 
    // You can even omit this check if you can rely on all children 
    // being application nodes. 
    if (v.first == "application") 
    { 
     std::string pkgId = v.second.get("id", ""); 
     std::string platform = v.second.get("platform", ""); 
     std::string version = v.second.get("version", ""); 
    } 
} 
+0

セバスチャンに詳細な返信をありがとうございます。あなたが提供したコードを試しましたが、毎回 "id:1"が表示されます。プラットフォーム:linux-x64およびバージョン:2.4何か案が ? – Neel

+0

少なくとも3回印刷しますか?私はコードをデバッグすることができないので、現時点で利用可能なBoost付きのコンピュータを持っていません。 –

+0

はい。それは3回印刷されます。 – Neel