質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

Q&A

解決済

1回答

8456閲覧

属性付きxmlの値を取得したいc++

ag_ns_gt

総合スコア15

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

0グッド

0クリップ

投稿2018/11/07 10:03

編集2018/11/07 10:20

前提・実現したいこと

<faces> <face id='0'> <bounds x='41' y='49' width='426' height='426'/> <right-eye x='161' y='208'/> <left-eye x='336' y='208'/> <features s-avg='0.76' s-min='0.40' s-max='0.93'> <point id='PR' x='167' y='204' s='0.86'/> <point id='PL' x='334' y='207' s='0.77'/> <point id='BR2' x='222' y='151' s='0.40'/> </features> </face> </faces> このようなxmlファイルのidとxの値とyの値をコマンドプロンプトに表示したいと思っています. visual studioのc++で行っています.

発生している問題・エラーメッセージ

ビルドは出来るのですが,デバッグをすると ハンドルされない例外が 0x00007FFDACAAF218 で発生しました (RBF.exe 内): Microsoft C++ の例外: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::property_tree::ptree_bad_path> > (メモリの場所 0x00000053470FF268)。 と表示されてしまいます.

該当のソースコード

c++

1struct Book { 2 std::string id; 3 std::string x; 4 5 Book() {} 6 7 Book(const Book& other) 8 : id(other.id), x(other.x) {} 9 10 Book(const std::string& id, const std::string& x) 11 : id(id), x(x) {} 12 13 void print() const 14 { 15 std::cout << id << "," << x << std::endl; 16 } 17}; 18 19 20void load(const std::string& filename) 21{ 22 using boost::property_tree::ptree; 23 24 std::vector<Book> books; 25 26 ptree pt; 27 read_xml(filename, pt); 28 29 foreach(const ptree::value_type& child_, pt.get_child("faces.face.features")) { 30 const ptree& child = child_.second; 31 const std::string id = child.get<std::string>("<xmlattr>.id"); 32 const std::string x = child.get<std::string>("<xmlattr>.x"); 33 34 books.push_back(Book(id, x)); 35 } 36 37 std::for_each(books.begin(), books.end(), boost::mem_fn(&Book::print)); 38} 39int main(int argc, char *argv[]) 40{ 41 load("parts.xml"); 42 return 0; 43 44}

試したこと

xmlファイルの名前が間違ったりしてないか何度も確認したり,xだけboost::optional<int>型にしてみたりしましたが上手くいきません.
xmlを扱うこと自体初めてで,c++も初心者なのでかみ砕いて教えていただけるとありがたいです.
printfでどこまで通っているか試したところ,void loadの
const ptree& child = child_.second;までは通っているので
const std::string id = child.getstd::string("<xmlattr>.id")
に問題があるようです.
よろしくお願いします.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

問題はptreeの子要素には属性が含まれているということです。
次のコードようにして、get_childで何を取ってきたのかを出力してみました。

cpp

1#include <iostream> 2#include <string> 3#include <boost/property_tree/ptree.hpp> 4#include <boost/property_tree/xml_parser.hpp> 5#include <boost/foreach.hpp> 6#include <boost/lexical_cast.hpp> 7 8struct Book { 9 std::string id; 10 std::string x; 11 12 Book() {} 13 14 Book(const Book& other) 15 : id(other.id), x(other.x) {} 16 17 Book(const std::string& id, const std::string& x) 18 : id(id), x(x) {} 19 20 void print() const 21 { 22 std::cout << id << "," << x << std::endl; 23 } 24}; 25 26 27void load(const std::string& filename) 28{ 29 using boost::property_tree::ptree; 30 31 std::vector<Book> books; 32 33 ptree pt; 34 read_xml(filename, pt); 35 36 BOOST_FOREACH(const ptree::value_type& child_, pt.get_child("faces.face.features")) { 37 std::cout << child_.first << std::endl; 38 } 39 40 for(auto&& book: books) book.print(); 41} 42int main(int argc, char *argv[]) 43{ 44 load("parts.xml"); 45 return 0; 46 47}

すると、childのfirstの文字列は次のように出力されます。

<xmlattr> point point point

一個目の要素は<xmlattr>なのでの属性ですが、属性からid属性等を取ろうとして、そんな要素はありませんよと例外が送出されています。

雑な解決方法はif文で要素の文字列を判定することでしょう。

cpp

1#include <iostream> 2#include <string> 3#include <boost/property_tree/ptree.hpp> 4#include <boost/property_tree/xml_parser.hpp> 5#include <boost/foreach.hpp> 6#include <boost/lexical_cast.hpp> 7 8struct Book { 9 std::string id; 10 std::string x; 11 12 Book() {} 13 14 Book(const Book& other) 15 : id(other.id), x(other.x) {} 16 17 Book(const std::string& id, const std::string& x) 18 : id(id), x(x) {} 19 20 void print() const 21 { 22 std::cout << id << "," << x << std::endl; 23 } 24}; 25 26 27void load(const std::string& filename) 28{ 29 using boost::property_tree::ptree; 30 31 std::vector<Book> books; 32 33 ptree pt; 34 read_xml(filename, pt); 35 36 BOOST_FOREACH(const ptree::value_type& child_, pt.get_child("faces.face.features")) { 37 if(auto [tag, data] = child_; tag == "point"){ 38 books.emplace_back( data.get<std::string>("<xmlattr>.id"), data.get<std::string>("<xmlattr>.x") ); 39 } 40 } 41 42 for(auto&& book: books) book.print(); 43} 44int main(int argc, char *argv[]) 45{ 46 load("parts.xml"); 47 return 0; 48 49}

Wandboxで実行してみる

投稿2018/11/07 11:30

編集2018/11/08 04:50
mitama_rs

総合スコア165

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ag_ns_gt

2018/11/08 05:27

auto[tag,data]のところに識別子tagが定義されていません。というのと tagはauto型を推測できません。初期化子が必要です。 と出てきてしまいました。 申し訳ありませんがよろしくお願いします。
mitama_rs

2018/11/08 06:01

すいません、これはC++17の構造化束縛という機能を使っています。 比較的新しいコンパイラでC++17でコンパイルしないと通らないとおもいます。 お使いのC++のバージョンはどれでしょうか? こういう齟齬を防止するために、質問にはtoolchainや開発環境を付属することが推奨されていますよ。 (ちなみに仕事でC++17を使っているので僕はこれが普通なのです。。。)
ag_ns_gt

2018/11/08 06:56

すいません。 知りませんでした。 visual studio 2017の15.8.1です.
mitama_rs

2018/11/08 07:08 編集

visual studio 2017の15.8.1であればほぼ最新ですね、サービス更新が8回ほど入ってないですが。 個人的にはC++17を使ってしまうのをオススメしますが。 Visual Studioは最近使っていないので忘れました。 >よろしくお願いします。 とありますが、何をどうよろしくすればいいのかイマイチわかりかねるところです。 めんどくさいのでC++11でも通るコードを示します。 https://wandbox.org/permlink/WXtd14oP43n8QhJC
ag_ns_gt

2018/11/08 08:12

出来ました! とても勉強になりました。 本当に感謝しています。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問