web-dev-qa-db-ja.com

Boostを使用してXMLファイルを読み書きする

Boostを使用してXMLファイルを読み書きする良い方法(そして簡単な方法)はありますか?

Boostを使用してXMLファイルを読み取るための簡単なサンプルは見つかりません。 Boostを使用してXMLファイルの読み取りと書き込みを行う簡単なサンプルを教えてください。

Boostでない場合、推奨できるXMLファイルを読み書きするための優れたシンプルなライブラリはありますか? (C++ライブラリでなければなりません)

68
Nuno

試してみてください pugixmlC++用の軽量でシンプルで高速なXMLパーサー

Pugixmlの最も良い点は、XPathサポートです。TinyXMLおよびRapidXMLにはありません。

RapidXMLの著者である「このプロジェクトのインスピレーションとなったpugixmlの研究についてArseny Kapoulkineに感謝したい」と「バージョン0.3に対してテストしたXMLパーサーであるpugixmlよりも5%-30%高速」最近バージョン0.42に達したpugixmlの。

Pugixmlドキュメントからの抜粋を次に示します。

主な機能は次のとおりです。

  • 低メモリ消費と断片化(pugxmlの勝ちは〜1.3倍、TinyXML-〜2.5倍、Xerces(DOM)-〜4.3倍1)。正確な数値は、既存のパーサーとの比較セクションで確認できます。
  • 非常に高速な解析速度(pugxmlの勝ちは6倍、TinyXML-10倍、Xerces-DOM-17.6倍1
  • 非常に高速な解析速度(まあ、繰り返しますが、テストXMLでExpatを2.8倍上回るほど高速です)2
  • 多かれ少なかれ標準準拠(DTD関連の問題を除き、標準準拠のファイルを正しく解析します)
  • かなりエラーを無視します(expatのようにYou&Meのようなものを止めません;間違ったエンコーディングのデータを含むファイルを解析します;など)
  • クリーンなインターフェイス(大幅にリファクタリングされたpugxmlのインターフェイス)
  • 多かれ少なかれUnicode対応(実際は、入力データのUTF-8エンコーディングを想定していますが、ANSIで容易に動作します-現在はUTF-16なし(将来の作業を参照)、ヘルパー変換関数(UTF-8 <- > UTF-16/32(std :: wstring&wchar_tのデフォルトは何でも)
  • 完全に標準に準拠したC++コード(Comeau strictモードで承認);ライブラリはマルチプラットフォームです(プラットフォームリストのリファレンスを参照)
  • 高い柔軟性。解析オプションを使用して、ファイル解析およびDOMツリー構築の多くの側面を制御できます。

さて、あなたは尋ねるかもしれません-キャッチは何ですか?すべてがとてもかわいい-それは、XMLを解析するための小さく、高速で、堅牢で、クリーンなソリューションです。何が欠けている?わかりました、私たちは公正な開発者です-だからここに誤機能リストがあります:

  • メモリ消費。私が知っているすべてのDOMベースのパーサーよりも優れていますが、SAXパーサーが登場したとき、チャンスはありません。 4 Gb未満のメモリで2 GbのXMLファイルを処理することはできません-高速に実行できます。 pugixmlは他のすべてのDOMベースのパーサーよりも優れた動作をしますが、DOMにこだわっていても問題はありません。
  • メモリ消費。わかりました、繰り返します。再び。他のパーサーを使用してXMLファイルを定数ストレージに(またはメモリマップ領域として)提供できる場合、pugixmlは提供しません。そのため、データ全体を非定数ストレージにコピーする必要があります。さらに、パーサーの存続期間中も存続する必要があります(その理由と存続期間についての詳細は以下に記載されています)。繰り返しになりますが、DOMに問題がなければ、全体的なメモリ消費量は少ないので、問題ではないはずです(ただし、連続したメモリチャンクが必要になりますが、これは問題になる可能性があります)。
  • 検証の欠如、DTD処理、XML名前空間、エンコードの適切な処理。これらが必要な場合は、MSXMLやXercesCなどを使用してください。
63
Cristian Adam

TinyXML はおそらく良い選択です。 Boostの場合:

Boost RepositoryProperty_Tree ライブラリがあります。それは受け入れられましたが、現時点ではサポートが不足しているようです(編集: Property_Tree は今ではBoostの一部です バージョン1.41以降 、読んでください ドキュメント =そのXML機能に関して)。

Daniel Nufferは、Boost Spiritに xmlパーサー を実装しました。

23
stephan

TinyXML もあります。これは小さくて素敵なC++ライブラリです。下位レベルのライブラリを探している場合、 RapidXML が出発点として最適です。

16
Anteru

BoostRapidXML を使用します- chapterXML Parserof pageプロパティツリーを作成する方法

残念ながら、この記事の執筆時点では [〜#〜] xml [〜#〜] パーサーには Boost がありません。そのため、ライブラリには高速で小さな RapidXML パーサー(現在バージョン1.13)が含まれており、XML解析サポートを提供します。 RapidXMLはXML標準を完全にサポートしていません。 DTDを解析できないため、完全なエンティティ置換を行うことはできません。

XML boost tutorial も参照してください。

OPは "boostを使用してxmlファイルを読み書きする簡単な方法"を必要としているため、非常に基本的な例を以下に示します。

_<main>
    <owner>Matt</owner>
    <cats>
        <cat>Scarface Max</cat>
        <cat>Moose</cat>
        <cat>Snowball</cat>
        <cat>Powerball</cat>
        <cat>Miss Pudge</cat>
        <cat>Needlenose</cat>
        <cat>Sweety Pie</cat>
        <cat>Peacey</cat>
        <cat>Funnyface</cat>
    </cats>
</main>
_

(猫の名前は Matt Mahoneyのホームページ

C++の対応する構造:

_struct Catowner
{
    std::string           owner;
    std::set<std::string> cats;
};
_

read_xml() 使用法:

_#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

Catowner load(const std::string &file)
{
    boost::property_tree::ptree pt;
    read_xml(file, pt);

    Catowner co;

    co.owner = pt.get<std::string>("main.owner");

    BOOST_FOREACH(
       boost::property_tree::ptree::value_type &v,
       pt.get_child("main.cats"))
       co.cats.insert(v.second.data());

    return co;
}
_

write_xml() 使用法:

_void save(const Catowner &co, const std::string &file)
{
   boost::property_tree::ptree pt;

   pt.put("main.owner", co.owner);

   BOOST_FOREACH(
      const std::string &name, co.cats)
      pt.add("main.cats.cat", name);

   write_xml(file, pt);
}
_
10
olibre

BoostはXMLパーサーATMを提供しません。

Poco XML( Poco C++ libs の一部)は適切でシンプルです。

4
StackedCrooked

XML解析用の特定のライブラリはありませんが、多くの選択肢があります。ここにいくつかあります: libxmlXercesExpat

もちろん、他のライブラリをブーストして使用して、独自のライブラリを作成することもできますが、それはおそらくかなりの作業です。

そして、これは 全記事 IBMの主題についてです。

4
Skurmedel

目的に十分であれば、ブーストシリアル化でXMLのアーカイブの読み取りと書き込みができるようです。

Boostを使用したより簡単なXML

4
Stuart

DefinatellyはTinyXMLを使用します*サムスアップ*

3
StfnoPad

DOM機能のみを探している場合、このスレッドにはすでにいくつかの提案があります。私は個人的にはおそらくXPathサポートのないライブラリを気にしませんし、C++ではQtを使用します。 TinyXPathもあり、アラビカはXPathをサポートしていると主張していますが、それらについては何も言えません。

2
Vladimir Prus

Arabica をご覧ください

2

Boostメーリングリストに潜んでいる私の経験から、XMLが主題として登場するたびに、それはUnicodeに関する議論に流用されているように見えます。ただし、現在、潜在的なUnicodeライブラリが間近に迫っているので、XMLライブラリがそこに表示されるのにそれほど時間がかかるとは思わない。

それまでの間、私もTinyXMLを使用しています。

RapidXMLに関する興味深いリンク。それを見てみましょう。

1
Kaz Dragon

Boost.XMLの既存の提案を改善するためにGSoCが提案した作業があります: https://github.com/stefanseefeld/boost.xml しかしAndrzejとして提案されたBoost.PropertyTreeはこのタスクに適しています。自然に必要なxmlサイズと検証サポートに依存します。

Boostメーリングリストで最近提案されたライブラリもあります: http://www.codesynthesis.com/projects/libstudxml/doc/intro.xhtml

1
daminetreg

警告。 RapidXMLは大好きですが、UTF16を解析するときに非常に厄介なバグがあります。有効な値によってはクラッシュする場合があります。

Pugixmlをお勧めしたいのですが、名前空間のサポートが欠けているため、問題が発生する可能性があります。

1

Boost.spiritはどうですか?

ここ 、「Mini XML」パーサーが表示されます

0
tagoma
<?xml version="1.0"?>
<Settings>
  <GroupA>
      <One>4</One>
      <Two>7</Two>
      <Three>9</Three> 
  </GroupA>
  <GroupA>
      <One>454</One>
      <Two>47</Two>
      <Three>29</Three> 
  </GroupA>
  <GroupB>
      <A>String A</A>
      <B>String B</B>  
  </GroupB>  
</Settings>

BOOSTを使用してXMLを簡単に読み取る方法があります。この例は、std :: wstringベースの場合です:

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

bool CMyClass::ReadXML(std::wstring &full_path)
{
    using boost::property_tree::wptree;

    // Populate tree structure pt:
    wptree pt;
    std::wstringstream ss; ss << load_text_file(full_path); // See below for ref.
    read_xml(ss, pt);

    // Traverse pt:
    BOOST_FOREACH(wptree::value_type const& v, pt.get_child(L"Settings"))
    {
        if (v.first == L"GroupA")
        {
            unsigned int n1 = v.second.get<unsigned int>(L"One");
            unsigned int n2 = v.second.get<unsigned int>(L"Two");
            unsigned int n3= v.second.get<unsigned int>(L"Three");
        }
        else if (v.first == L"GroupB")
        {
            std::wstring wstrA = v.second.get<std::wstring>(L"A");
            std::wstring wstrB = v.second.get<std::wstring>(L"B");
        }
    };
}

属性を読み取ることは、もう少し複雑です。

-

参考のために:

std::wstring load_text_file(std::wstring &full_path)
{
    std::wifstream wif(full_path);

    wif.seekg(0, std::ios::end);
    buffer.resize(wif.tellg());
    wif.seekg(0);
    wif.read(buffer.data(), buffer.size());

    return buffer;
}
0
Amit G.