2011-03-28 21 views
0

我想分享一下當我試圖在C++中使用RapidXML進行XML解析時偶然發現的奇怪但有趣的情況。使用RapidXML/C++類指針進行分析時的遞歸問題副作用

我想編寫一個遞歸函數來搜索並返回給定節點的子節點中的特定節點。我的第一個嘗試是:

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循環似乎運行一次(或多次)(可能是因爲遞歸的調用堆棧),然後退出並且指針丟失。

於是,我就用一個臨時變量解決這個問題,這樣一來:

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

當您通過遞歸找到孩子時,將其返回。如果你沒有找到一個孩子,返回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; 
} 
+0

我絕對想過太多..你的解決方案的工作.. :) – ascanio 2011-03-28 21:46:46

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");