2008-09-01 66 views
12

私のC++プログラムでは、小さなXMLを解析し、いくつかのノードを挿入してから、新しいXML(好ましくはstd::string)を抽出します。
RapidXmlが推奨されていますが、XMLをテキスト文字列として取得する方法はわかりません。
(私はノードと属性を繰り返し処理して自分で構築することができますが、確かに欠けている機能のビルドがあります)
ありがとうございます。あなたはまだ急速なXMLにコミットされていない場合はC++:RapidXmlから文字列を抽出する方法

答えて

9

Althougこのトピックではドキュメンテーションが貧弱なため、ソースを参照して作業コードを取得することができました。通常は重要な情報が含まれているxmlヘッダーがありません。

#include <iostream> 
#include <sstream> 
#include "rapidxml/rapidxml.hpp" 
#include "rapidxml/rapidxml_print.hpp" 

int main(int argc, char* argv[]) { 
    char xml[] = "<?xml version=\"1.0\" encoding=\"latin-1\"?>" 
       "<book>" 
       "</book>"; 

    //Parse the original document 
    rapidxml::xml_document<> doc; 
    doc.parse<0>(xml); 
    std::cout << "Name of my first node is: " << doc.first_node()->name() << "\n"; 

    //Insert something 
    rapidxml::xml_node<> *node = doc.allocate_node(rapidxml::node_element, "author", "John Doe"); 
    doc.first_node()->append_node(node); 

    std::stringstream ss; 
    ss <<*doc.first_node(); 
    std::string result_xml = ss.str(); 
    std::cout <<result_xml<<std::endl; 
    return 0; 
} 
0

が、私はいくつかの代替ライブラリをお勧めすることができます:

  • のXercesを - これはおそらく事実上のC++実装です。

  • XMLite - 私はこの最小限のXML実装で多少の運がありました。あなたはXMLを自分で構築した場合は、特殊文字をエスケープすることを忘れないでくださいhttp://www.codeproject.com/KB/recipes/xmlite.aspx

+0

これらのライブラリでは数百パーセントのスピード違反を忘れてはいけませんが、どちらもRapidXMLよりも多くの機能を備えています。 –

+0

vtd-xmlはrapidXMLよりも適合性が高く、強力です。 –

2

での記事を参照してください。これは見落とされる傾向にあるが、それが実装されていない場合は、いくつかの深刻な頭痛を引き起こす可能性があります:

  • <               & LT;
  • >               & GT。
  • &               &アンペア。
  • "               & QUOT。
  • '               & 4'-
6

使用print機能(rapidxml_print.hppユーティリティヘッダーで見つかった)stringstreamにXMLノードの内容を印刷する:ここでは、rapidxmlを使用して探しているものを行い、小さなプログラム例です。ここで

+0

優れているので、ノードの字下げを抑制できます – hamishmcn

+0

例を挙げることはできますか? – Qsiris

2

がまっすぐRapidXML Manualから文字列にノードを印刷する方法は次のとおりです。

xml_document<> doc; // character type defaults to char 
// ... some code to fill the document 

// Print to stream using operator << 
std::cout << doc; 

// Print to stream using print function, specifying printing flags 
print(std::cout, doc, 0); // 0 means default printing flags 

// Print to string using output iterator 
std::string s; 
print(std::back_inserter(s), doc, 0); 

// Print to memory buffer using output iterator 
char buffer[4096];      // You are responsible for making the buffer large enough! 
char *end = print(buffer, doc, 0);  // end contains pointer to character after last printed character 
*end = 0;        // Add string terminator after XML 
2

rapidxml :: printは出力を生成する出力イテレータをreuqires、その文字列は、それに対応しています。しかし、固定長(2048バイトなど)の配列がXMLのすべての内容を保持するのに十分な長さかどうかわからないため、これは危険です。

これを行う正しい方法は、文字列ストリームの出力イテレータを渡すことで、XMLがその中にダンプされているときにバッファを展開できるようにすることです。

私のコードは次のようなものです:あなたが唯一のに必要

std::string s; 
print(back_inserter(s), doc, 0); 
cout << s; 

rapidxml::xml_document<> doc; 
rapidxml::xml_node <> * root_node = doc.first_node(); 
std::string strBuff; 

doc.parse<0>(xml); 

. 
. 
. 
strBuff = static_cast<std::string>(root_node->first_attribute("attribute_name")->value()); 
0

使用することは>

<

例ををstatic_cast 「rapidxml _print.hpp "ヘッダーをソースコードに追加します。

0

に続いて、非常に簡単です:

std::stringstream stream; 
std::ostream_iterator<char> iter(stream); 

rapidxml::print(iter, doc, rapidxml::print_no_indenting); 

printf("%s\n", stream.str().c_str()); 
printf("len = %d\n", stream.str().size()); 
関連する問題