0

C ++でのXML解析にRapidXMLを使用しようとしたときに、最近遭遇したこの奇妙で興味深い状況を共有したいと思います。

特定のノードの子の中から特定のノードを検索して返す再帰関数を作成したかったのです。私の最初の試みは:

xml_node<>* get_child(xml_node<> *inputNode, string sNodeFilter)
{
    // cycles every child
    for (xml_node<> *nodeChild = inputNode->first_node(); nodeChild; nodeChild = nodeChild->next_sibling())
    {
        if (nodeChild->name() == sNodeFilter)
        {
            cout << "node name " << nodeChild->name() << "\n";
            cout << "nodeChild " << nodeChild << endl;
            // returns the desired child
            return nodeChild;
        }
        get_child(nodeChild, sNodeFilter);
    }
}

たまたま最初の子でのみ正しく機能しましたが、XMLファイルのより深いところにネストされているノードを検索すると、ノードが見つかります(coutが表示されます)が、returnステートメントの後にforサイクルが1つ実行されているようです(またはいくつか)より多くの時間(おそらく再帰の呼び出しスタックのため)、それから終了し、ポインタが失われます。

だから私は一時変数でそれを修正しようとしました、このように:

xml_node<>* get_child(xml_node<> *inputNode, string sNodeFilter)
{
    xml_node<> *outputNode;
    // cycles every child
    for (xml_node<> *nodeChild = inputNode->first_node(); nodeChild; nodeChild = nodeChild->next_sibling())
    {
        if (nodeChild->name() == sNodeFilter)
        {
            cout << "node name " << nodeChild->name() << "\n";
            cout << "nodeChild " << nodeChild << endl;
            outputNode = nodeChild;
            cout << "outputNode " << outputNode << endl;
            // returns the desired child
            return outputNode;
        }
        get_child(nodeChild, sNodeFilter);
    }
}

しかし、何も変わりませんでした。

残念ながら、RapidXMLのノードはクラスポインタであるため、この状況では、副作用により正しい結果を引き出すことができません。

誰かがこの状況を発見したか、または別の方法でこの問題を解決しましたか?

4

2 に答える 2

4

繰り返して子供を見つけたら、返してください。子供が見つからない場合は、0を返します

xml_node<>* get_child(xml_node<> *inputNode, string sNodeFilter)
{
    // cycles every child
    for (xml_node<> *nodeChild = inputNode->first_node(); nodeChild; nodeChild = nodeChild->next_sibling())
    {
        if (nodeChild->name() == sNodeFilter)
        {
            cout << "node name " << nodeChild->name() << "\n";
            cout << "nodeChild " << nodeChild << endl;
            // returns the desired child
            return nodeChild;
        }
        xml_node<> * x = get_child(nodeChild, sNodeFilter);
        if (x) 
          return x;
    }
    return 0;
}
于 2011-03-28T21:27:50.053 に答える
1

私はこれが質問に直接答えないことを知っています、しかし私はそれが他の誰かを助けることができることを願っています:

この関数は、ある親ノードの下にある特定の名前のすべてのノードを再帰的に検索する場合に役立ちます。結果を含むベクトルを返します。

vector<xml_node<>*> find_nodes(xml_node<>* parent, const char* name) {
    vector<xml_node<>*> ret;
    if (parent != 0) {
        if (strcmp(parent->name(), name) == 0) {
            ret.push_back(parent);
        }
        for (xml_node<>* it = parent->first_node(); it != 0; it = it->next_sibling()) {
            vector<xml_node<>*> tmp = find_nodes(it, name);
            ret.insert(ret.end(), tmp.begin(), tmp.end());
        }
    }
    return ret;
}

使用例:

vector<xml_node<>*> nodes = find_nodes(some_node, "link");

また、ドキュメント全体でも機能します。

xml_document<> doc;
doc.parse<0>(str);  // parse some string

vector<xml_node<>*> nodes = find_nodes(&doc, "link");
于 2014-11-24T13:37:12.067 に答える