9

XML ファイルに多数の階層データが格納されています。TinyXML を使用して手作りのクラスの背後にそれをまとめています。ソース署名を (頻度、レベル) のペアのセットとして記述する XML フラグメントを考えると、次のようになります。

<source>
  <sig><freq>1000</freq><level>100</level><sig>
  <sig><freq>1200</freq><level>110</level><sig>
</source>

私はこれでペアを抽出しています:

std::vector< std::pair<double, double> > signature() const
{
    std::vector< std::pair<double, double> > sig;
    for (const TiXmlElement* sig_el = node()->FirstChildElement ("sig");
        sig_el;
        sig_el = sig_el->NextSiblingElement("sig"))
    {
        const double level = boost::lexical_cast<double> (sig_el->FirstChildElement("level")->GetText());
        const double freq =  boost::lexical_cast<double> (sig_el->FirstChildElement("freq")->GetText());
        sig.push_back (std::make_pair (freq, level));
    }
    return sig;
}

node() はノードを指してい<source>ます。

質問: 代わりに XPath ライブラリを使用して、よりきちんとした、より洗練された、より保守しやすい、または他の方法でより優れたコードを取得できますか?

更新: TinyXPath を 2 つの方法で使用してみました。どちらも実際には機能しません。これは明らかにそれらに対する大きなポイントです。私は根本的に間違ったことをしていますか?これが XPath でどのように見えるかということであれば、何も得られないと思います。

std::vector< std::pair<double, double> > signature2() const
{
    std::vector< std::pair<double, double> > sig;
    TinyXPath::xpath_processor source_proc (node(), "sig");
    const unsigned n_nodes = source_proc.u_compute_xpath_node_set();
    for (unsigned i = 0; i != n_nodes; ++i)
    {
        TiXmlNode* s = source_proc.XNp_get_xpath_node (i);
        const double level = TinyXPath::xpath_processor(s, "level/text()").d_compute_xpath();
        const double freq =  TinyXPath::xpath_processor(s, "freq/text()").d_compute_xpath();
        sig.push_back (std::make_pair (freq, level));
    }
    return sig;
}

std::vector< std::pair<double, double> > signature3() const
{
    std::vector< std::pair<double, double> > sig;
    int i = 1;
    while (TiXmlNode* s = TinyXPath::xpath_processor (node(), 
        ("sig[" + boost::lexical_cast<std::string>(i++) + "]/*").c_str()).
        XNp_get_xpath_node(0))
    {
        const double level = TinyXPath::xpath_processor(s, "level/text()").d_compute_xpath();
        const double freq =  TinyXPath::xpath_processor(s, "freq/text()").d_compute_xpath();
        sig.push_back (std::make_pair (freq, level));
    }
    return sig;
}

二次的な問題として、もしそうなら、どの XPath ライブラリを使用する必要がありますか?

4

4 に答える 4

5

一般に、私はその簡潔さと汎用性のためにXPathベースのソリューションを好む傾向がありますが、正直なところ、あなたの場合、XPathを使用しても多くのことは得られないと思いますsignature

理由は次のとおりです。

コードの優雅さ
あなたのコードは素晴らしくコンパクトであり、XPath式ではこれ以上良くなることはありません。

メモリフットプリント
入力XML構成ファイルが巨大で(一種のオキシモロン)、DOM解析で大きなメモリフットプリントが必要になる場合を除いて、XPathを使用することが決定的な治療法であるという証拠はありませんが、私はDOMを使い続けます。

実行速度
このような単純なXMLツリーでは、実行速度は同等である必要があります。違いがある場合は、特定のノードの下にタグfreqとタグが配置されているため、TinyXmlの利点になります。level

ライブラリと外部参照 それが決定的なポイントです。
C++の世界をリードするXPathエンジンはXQillaです。XQuery(したがって、XPath 1.0と2.0の両方)をサポートし、Berkeley DB製品(正確にはXQillaを使用するBerkeley DB XMLを含む)を担当するグループによって開発されているため、Oracleによってサポートされています。
XQillaを使用したいC++開発者にとっての問題は、いくつかの選択肢があることです。

  1. Xerces2とXQilla2.1を使用して、コードにキャストを散らかします。
  2. XQilla 2.2+を使用し、Xerces 3を使用します(ここではキャストは必要ありません)
  3. TinyXmlとうまく統合されたTinyXPathを使用しますが、いくつかの制限があります(たとえば、名前空間のサポートはありません)
  4. XercesとtinyXmlを混ぜる

要約すると、あなたの場合、それのためだけにXPathに切り替えることは、たとえあったとしてもほとんど利益をもたらさないでしょう。

それでも、XPathは今日の開発者ツールボックスの非常に強力なツールであり、誰もそれを無視することはできません。簡単な例で練習したいだけなら、あなたの例は何よりも優れています。次に、上記の点を念頭に置いて、とにかくTinyXPathを使用する可能性があります。

于 2011-03-05T07:34:56.797 に答える
3

抽出された値を実行時に変更できる柔軟性が必要な場合は、XPath が必要です。

ただし、この種の柔軟性が必要になる可能性が低い場合、または抽出するものを拡張するための再コンパイルは問題ではなく、物事が頻繁に変更されていない場合、またはユーザーが式を更新する必要がない場合. または、持っているものがうまく機能する場合は、XPath は必要なく、XPath を使用しないアプリケーションがたくさんあります。

より読みやすいかどうかについては、確かにそうです。しかし、いくつかの値を引き出すだけなら、別のライブラリを取り込む必要があるかどうか疑問に思います。

tinyxml や xml ライブラリに慣れていない人は、それが何をしているのかわからないかもしれませんが、そのままでは理解するのは難しくないので、あなたが現在持っているものをもう少し良く文書化します.

XPath がどのような種類のオーバーヘッドを追加するのかはわかりませんが、追加される可能性があると思われます。ほとんどの場合、違いにまったく気付かないと思いますし、あなたやほとんどの人にとっては気にならないかもしれませんが、気になる場合は注意してください.

xpath ライブラリを使用したい場合、私が言えることは、Xerces-C++に付属しているものを使用したことがあり、習得するのはそれほど難しくなかったということだけです。私は以前 TinyXML を使用したことがあり、ここで誰かがTinyXPathについて言及しています。経験はありませんが、利用可能です。

また、XPath 式について初めて学習するときに、このリンクが役立つこともわかりました。 http://www.w3schools.com/xpath/default.asp

于 2011-03-05T07:55:26.753 に答える
1

XPath はこのために作成されたものなので、もちろん、それを使用すればコードは「より良く」なります。

特定の c++ XPath ライブラリを推奨することはできませんが、ほとんどの場合、1 つを使用することが正しい決定であっても、追加する前に費用対効果の分析を行ってください。たぶんヤグニ

于 2011-03-04T14:31:41.523 に答える
1

この XPath 式:

/*/sig[$pN]/*

XML ドキュメントの最上位要素の$pN 番目の子のすべての子要素 ​​( と のペアのみ) をfreq選択します。levelsig

文字列$pNは、特定の正の整数に置き換える必要があります。次に例を示します。

/*/sig[2]/*

次の 2 つの要素を選択します

<freq>1200</freq><level>110</level>

XPath 式を使用すると、提供されている C++ コードよりもはるかに短く、理解できるようになります。

もう 1 つの利点は、同じ XPath 式をC# や Java などのプログラムから使用できることです。そのため、XPath に準拠することで、移植性が非常に高くなります。

于 2011-03-04T18:42:42.680 に答える