18

Boost ライブラリ (バージョン 1.52.0) を使用して C++ の XML 要素からいくつかの属性を処理しようとしているときに発生した問題を共有したいと思います。次のコードがあるとします。

#define ATTR_SET ".<xmlattr>"
#define XML_PATH1 "./pets.xml"

#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

using namespace std;
using namespace boost;
using namespace boost::property_tree;

const ptree& empty_ptree(){
    static ptree t;
    return t;
}

int main() {
    ptree tree;
    read_xml(XML_PATH1, tree);
    const ptree & formats = tree.get_child("pets", empty_ptree());
    BOOST_FOREACH(const ptree::value_type & f, formats){
        string at = f.first + ATTR_SET;
        const ptree & attributes = formats.get_child(at, empty_ptree());
        cout << "Extracting attributes from " << at << ":" << endl;
        BOOST_FOREACH(const ptree::value_type &v, attributes){
            cout << "First: " << v.first.data() << " Second: " << v.second.data() << endl;
        }
    }
}

次の XML 構造があるとします。

<?xml version="1.0" encoding="utf-8"?>
<pets>
    <cat name="Garfield" weight="4Kg">
        <somestuff/>
    </cat>
    <dog name="Milu" weight="7Kg">
        <somestuff/>
    </dog>
    <bird name="Tweety" weight="0.1Kg">
        <somestuff/>
    </bird>
</pets>

したがって、取得するコンソール出力は次のようになります。

Extracting attributes from cat.<xmlattr>:
First: name Second: Garfield
First: weight Second: 4Kg
Extracting attributes from dog.<xmlattr>:
First: name Second: Milu
First: weight Second: 7Kg
Extracting attributes from bird.<xmlattr>:
First: name Second: Tweety
First: weight Second: 0.1Kg

ただし、ルート ノードから下にあるすべての要素に共通の構造を使用することにした場合 (特定の属性からそれらを識別するため)、結果は完全に変わります。このような場合、これは XML ファイルである可能性があります。

<?xml version="1.0" encoding="utf-8"?>
<pets>
    <pet type="cat" name="Garfield" weight="4Kg">
        <somestuff/>
    </pet>
    <pet type="dog" name="Milu" weight="7Kg">
        <somestuff/>
    </pet>
    <pet type="bird" name="Tweety" weight="0.1Kg">
        <somestuff/>
    </pet>
</pets>

出力は次のようになります。

Extracting attributes from pet.<xmlattr>:
First: type Second: cat
First: name Second: Garfield
First: weight Second: 4Kg
Extracting attributes from pet.<xmlattr>:
First: type Second: cat
First: name Second: Garfield
First: weight Second: 4Kg
Extracting attributes from pet.<xmlattr>:
First: type Second: cat
First: name Second: Garfield
First: weight Second: 4Kg

3 つの属性セットが出力されているため、ルート ノードからぶら下がっている要素の数が適切に認識されているようです。それにもかかわらず、それらはすべて最初の要素の属性を参照しています...

私は C++ の専門家ではなく、Boost を初めて使用するので、ハッシュ マッピング処理などに関して欠けているものがあるかもしれません。アドバイスをいただければ幸いです。

4

3 に答える 3

19

プログラムの問題は次の行にあります。

const ptree & attributes = formats.get_child(at, empty_ptree());

この行を使用すると、子供を取得するように求められ、pet.<xmlattr>トラバースするものpetsに関係なく、これを3回実行します。この記事fに続いて、私はあなたが使用する必要があるものは次のとおりだと思います:

const ptree & attributes = f.second.get_child("<xmlattr>", empty_ptree());

両方のxmlファイルで機能する完全なコードは次のとおりです。

#define ATTR_SET ".<xmlattr>"
#define XML_PATH1 "./pets.xml"

#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

using namespace std;
using namespace boost;
using namespace boost::property_tree;

const ptree& empty_ptree(){
    static ptree t;
    return t;
}

int main() {
    ptree tree;
    read_xml(XML_PATH1, tree);
    const ptree & formats = tree.get_child("pets", empty_ptree());
    BOOST_FOREACH(const ptree::value_type & f, formats){
        string at = f.first + ATTR_SET;
        const ptree & attributes = f.second.get_child("<xmlattr>", empty_ptree());
        cout << "Extracting attributes from " << at << ":" << endl;
        BOOST_FOREACH(const ptree::value_type &v, attributes){
            cout << "First: " << v.first.data() << " Second: " << v.second.data() << endl;
        }
    }
}
于 2012-12-23T12:02:19.630 に答える
2

これまでこの機能を使用したことboost::property_treeがないので、XML パーサーは一般的な XML パーサーではなく、1 つの特定のプロパティに対して 1 つの特定のタグを持つ特定のスキーマを想定しているのではないかと思います。

機能を超えて XML を操作したい場合は、任意の XML スキーマの解析を提供する他の XML パーサーを使用することをお勧めしboost::property_treeます。Xerces C++Poco XMLなどをご覧ください。

于 2012-12-23T11:49:44.243 に答える