web-dev-qa-db-ja.com

C ++でのXMLパーサーを使うべきですか?

私は解析する必要のあるXML文書を持っていたり、XML文書を作成してそれをテキスト(ファイルかメモリのどちらか)に書く必要があります。 C++標準ライブラリにはこのためのライブラリがありませんので、私は何を使うべきですか?

注:これは最も確実なC++ - FAQ形式の質問です。だから、そう、それは他人の複製です。私はそれらの他の質問を単に適切にしませんでした。なぜならそれらはもう少し具体的なものを求める傾向があるからです。この質問はもっと一般的です。

317
Nicol Bolas

標準ライブラリコンテナと同様に、使用するライブラリはニーズによって異なります。便利なフローチャートを次に示します。

enter image description here

最初の質問はこれです:何が必要ですか?

完全なXMLコンプライアンスが必要

OK、XMLを処理する必要があります。おもちゃのXMLではなく、realXML。低位で解析しやすいビットだけでなく、XML仕様のallを読み書きできる必要があります。名前空間、DocType、エンティティ置換、作品が必要です。 W3C XML仕様全体。

次の質問は:APIはDOMまたはSAXに準拠する必要がありますか?

正確なDOMおよび/またはSAX準拠が必要

OK、だからあなたは本当にAPIがDOMやSAXである必要がある。 SAXスタイルのプッシュパーサーやDOMスタイルの保持されたパーサーだけではありません。 mustは、C++が許可する範囲で、実際のDOMまたは実際のSAXでなければなりません。

あなたが選択しました:

Xerces

それはあなたの選択です。 DOMおよびSAXに完全に準拠している(またはC++が許す限り)C++ XMLパーサー/ライターはほとんどありません。また、XIncludeのサポート、XMLスキーマのサポート、その他の多くの機能も備えています。

実際の依存関係はありません。 Apacheライセンスを使用します。

DOMやSAXの適合性を気にしない

あなたが選択しました:

LibXML2

LibXML2はCスタイルのインターフェースを提供します(実際に気になる場合はXercesを使用してください)が、インターフェースは少なくともオブジェクトベースであり、簡単にラップできます。 XIncludeサポート(コールバックを使用してファイルの取得元を特定できるようにする)、XPath 1.0認識機能、RelaxNGおよびSchematronサポート(エラーメッセージはロットが望ましい)など。

Iconvには依存関係がありますが、その依存関係なしで構成できます。これは、解析可能なテキストエンコーディングのセットがより限られていることを意味します。

MITライセンスを使用します。

XMLに完全に準拠する必要はありません

それでは、XMLへの完全な準拠は重要ではありません。 XMLドキュメントは完全に管理されているか、名前空間やエンティティなどのないXMLの「基本サブセット」を使用することが保証されています。

それで、あなたにとって何が重要ですか?次の質問は:XMLの作業で最も重要なことは何ですか?

最大XML解析パフォーマンス

アプリケーションは、XMLを取得し、この変換が発生する可能性がある限り高速にC++データ構造に変換する必要があります。

あなたが選択しました:

RapidXML

このXMLパーサーは、まさに「高速XML」です。ファイルをメモリにプルすることすら扱いません。それがどのように起こるかはあなた次第です。対処するのは、それを解析して、アクセス可能な一連のC++データ構造に変換することです。そして、これはファイルをバイトごとにスキャンするのと同じくらいの速さでこれを行います。

もちろん、無料のランチなどはありません。 XML仕様を気にしないほとんどのXMLパーサーと同様に、Rapid XMLは名前空間、DocType、エンティティ(文字エンティティと6つの基本的なXMLエンティティを除く)などには触れません。したがって、基本的にはノード、要素、属性などです。

また、DOMスタイルのパーサーです。したがって、すべてのテキストを読む必要があります。しかし、それは何もしませんcopyそのテキストのいずれか(通常)です。 RapidXMLが速度を最大限に活用する方法は、文字列in-placeを参照することです。これには、より多くのメモリ管理が必要です(RapidXMLがその文字列を見ている間、その文字列を維持する必要があります)。

RapidXMLのDOMは必要最低限​​です。物事の文字列値を取得できます。名前で属性を検索できます。それについてです。属性を他の値(数値、日付など)に変換する便利な関数はありません。文字列を取得するだけです。

RapidXMLのもう1つの欠点は、XMLの書き込みに苦痛を伴うことです。 DOMを構築するには、文字列名の明示的なメモリ割り当てを多数行う必要があります。それは一種の文字列バッファを提供しますが、それでもあなたの側で多くの明示的な作業が必要です。確かに機能的ですが、使用するのは苦痛です。

MITライセンスを使用します。依存関係のないヘッダーのみのライブラリです。

パフォーマンスは気になりますが、それほど重要ではありません

はい、パフォーマンスはあなたにとって重要です。ただし、必要最低限​​のものが必要な場合があります。より多くのUnicodeを処理できるもの、またはユーザーが制御するメモリ管理をそれほど必要としないものかもしれません。パフォーマンスは依然として重要ですが、もう少し直接的なものが必要です。

あなたが選択しました:

PugiXML

歴史的に、これはRapidXMLのインスピレーションとして機能しました。しかし、2つのプロジェクトは分岐しており、Pugiはより多くの機能を提供し、RapidXMLは完全に速度に重点を置いています。

PugiXMLはUnicode変換サポートを提供します。そのため、UTF-16ドキュメントがいくつかあり、それらをUTF-8として読みたい場合は、Pugiが提供します。そのようなものが必要な場合は、XPath 1.0実装もあります。

しかし、プギはまだ非常に高速です。 RapidXMLと同様に、依存関係はなく、MITライセンスの下で配布されます。

巨大なドキュメントを読む

サイズがギガバイトで測定されるドキュメントを読む必要があります。たぶん、あなたはそれらを他のプロセスによって供給されている標準入力から取得しているのでしょう。または、大容量ファイルからそれらを読んでいます。または何でも。ポイントは、notを処理するためにファイル全体を一度にメモリに読み込む必要があることです。

あなたが選択しました:

LibXML2

XercesのSAXスタイルのAPIはこの容量で動作しますが、LibXML2は、操作が少し簡単なのでここにあります。 SAXスタイルのAPIはプッシュAPIです。ストリームの解析を開始し、キャッチする必要があるイベントを発生させます。コンテキスト、状態などを管理する必要があります。 SAXスタイルのAPIを読み取るコードは、予想以上に広範に広がっています。

LibXML2のxmlReaderオブジェクトはプルAPIです。次のXMLノードまたは要素に移動するようにに求めます。あなたは言われません。これにより、さまざまなエンティティを、コールバックの束よりもコードではるかに読みやすい方法で処理するために、コンテキストを適切に格納できます。

代替案

Expat

Expatは、プルパーサーAPIを使用する有名なC++パーサーです。それはジェームズ・クラークによって書かれました。

現在のステータスはアクティブです。最新バージョンは2.2.5で、先月(2017-10-31)にリリースされました。

LlamaXML

これは、StAXスタイルのAPIの実装です。これは、LibXML2のxmlReaderパーサーに似たプルパーサーです。

しかし、2005年以降は更新されていません。繰り返しになりますが、Caveat Emptorです。

XPathサポート

XPathは、XMLツリー内の要素を照会するためのシステムです。これは、標準化された構文を使用して、共通のプロパティによって要素または要素のコレクションに効果的に名前を付ける便利な方法です。多くのXMLライブラリはXPathサポートを提供します。

ここには、実質的に3つの選択肢があります。

  • LibXML2:XPath 1.0を完全にサポートします。繰り返しになりますが、これはC APIであるため、それが面倒な場合は代替手段があります。
  • PugiXML:XPath 1.0サポートも付属しています。上記のように、それはLibXML2よりもC++ APIに近いため、使いやすいかもしれません。
  • TinyXML:XPathサポートは付属していませんが、TinyXPathそれを提供するライブラリ。 TinyXMLはバージョン2.0への変換中です。これによりAPIが大幅に変更されるため、TinyXPathは新しいAPIで動作しない可能性があります。 TinyXML自体と同様に、TinyXPathはzLibライセンスの下で配布されます。

仕事を片付ける

したがって、XMLの正確性は気にしません。パフォーマンスはあなたにとって問題ではありません。ストリーミングは無関係です。必要なのはsomethingだけで、これによりXMLがメモリに格納され、XMLをディスクに戻すことができます。 youが気にするのはAPIです。

小さく、インストールが簡単で、使用が簡単で、最終的な実行可能ファイルのサイズに関係ないほど十分に小さいXMLパーサーが必要です。

あなたが選択しました:

TinyXML

TinyXMLをこのスロットに配置したのは、XMLパーサーが取得するのと同じくらい簡単に使用できるためです。はい、遅いですが、簡単で明白です。属性などを変換するための便利な機能がたくさんあります。

TinyXMLではXMLの記述は問題ありません。いくつかのオブジェクトをnewだけアップし、それらを結合し、ドキュメントをstd::ostreamに送信するだけで、誰もが満足します。

また、TinyXMLを中心に構築されたエコシステムのようなものがあり、イテレータフレンドリーなAPI、さらにその上にXPath 1.0実装が重ねられています。

TinyXMLはzLibライセンスを使用しますが、これは多かれ少なかれMITライセンスとは異なる名前です。

634
Nicol Bolas

XMLデータバインディングと呼ばれる、XMLを処理するためのもう1つのアプローチがあります。特にあなたがすでにあなたのXML語彙の正式な仕様を持っているなら、例えばXMLスキーマで。

XMLデータバインディングを使用すると、実際にXMLの解析やシリアル化を行わなくてもXMLを使用できます。データバインディングコンパイラは、すべての低レベルコードを自動生成し、解析したデータをアプリケーションドメインに対応するC++クラスとして表示します。その後、関数を呼び出して、文字列を比較してテキストを解析するのではなく、C++型(int、doubleなど)を使用してこのデータを処理します(これは、DOMやSAXなどの低レベルXMLアクセスAPIで行います)。

たとえば、私が書いたオープンソースのXMLデータバインディングの実装、 CodeSynthesis XSD 、および軽量で依存性のないバージョンについては、 コード合成XSD/e

17
Boris Kolpackov

Secured Globe 、Inc.では、 rapidxml を使用しています。他のすべてを試しましたが、rapidxmlが私たちにとって最良の選択であるように思われます。

これが一例です。

 rapidxml::xml_document<char> doc;
    doc.parse<0>(xmlData);
    rapidxml::xml_node<char>* root = doc.first_node();

    rapidxml::xml_node<char>* node_account = 0;
    if (GetNodeByElementName(root, "Account", &node_account) == true)
    {
        rapidxml::xml_node<char>* node_default = 0;
        if (GetNodeByElementName(node_account, "default", &node_default) == true)
        {
            swprintf(result, 100, L"%hs", node_default->value());
            free(xmlData);
            return true;
        }
    }
    free(xmlData);
0

Expatに関するもう1つの注意点:組み込みシステムの動作を調べる価値があります。ただし、Web上で見つけられる可能性のあるドキュメントは古く、間違っています。ソースコードは実際にはかなり徹底的な機能レベルのコメントを持っています、しかしそれはそれらが意味をなすためにいくらか熟読を要するでしょう。

0
breakpoint

私のものも入れてください。

http://www.codeproject.com/Articles/998388/XMLplusplus-version-The-Cplusplus-update-of-my-XML

XML検証機能はありませんが、高速です。

0

それではリストのどれも私のニーズを満足させるものではなかったので、私は新しいものを作成しました。

利点:

  1. 低レベルでのプルパーサストリーミングAPI( Java StAXのような
  2. サポートされている例外とRTTIモード
  3. メモリ使用量の制限、大きなファイルのサポート(100 mib XMarkファイル でテスト済み、速度はハードウェアに依存)
  4. UNICODEのサポート、および入力ソースのエンコーディングの自動検出
  5. 構造/ POCO に読み込むための高レベルAPI
  6. Xml構造(属性とネストタグ)をサポートする 構造/ POCO からXSDを作成および生成するためのメタプログラミングAPIデバッグ時にのみ使用してください。
  7. C++ 11 - GCCとVC++ 15+

デメリット:

  1. DTDとXSDの検証はまだ提供されていません
  2. HTTP/HTTPSによるXML/XSDの取得が進行中ですが、まだ実行されていません
  3. 新しい図書館

プロジェクトホーム

0
Victor Gubin