2014-09-02 179 views
0

我不允許創建新標籤'tinyxml2',這就是爲什麼我使用標籤'tinyxml',但是我使用'tinyxml2'!使用tinyxml2從文本插入子樹到現有的XML文件中

我想插入一個子樹元素到現有的XML文件。我的問題是,在運行程序並檢查XML文件後,子樹根本不存在於文檔中。在原始代碼中,我也在加載和保存文件時檢查錯誤,因此這些函數沒有問題,它們工作正常。我嘗試了幾種不同的方法,並使用UserList.NewElement(*name*)-函數添加單個元素也能正常工作。 現在我要插入一個文本變量整個子樹...

我的最新的方法是這樣的(但不檢查LoadFileSaveFile簡化):

tinyxml2::XMLDocument UserList; 
UserList.LoadFile(*Path*); 

const char* XMLText = "<user name=\"test-user\" gender=\"male\"><ability description=\"I_can_do_magic\" /></user>"; 

tinyxml2::XMLDocument TestParse; 
TestParse.Parse(XMLText); 
tinyxml2::XMLElement* myNewUser = TestParse.RootElement(); 
UserList.FirstChildElement("magicians")->InsertEndChild(myNewUser); 
UserList.SaveFile(*Path*); 

順便說一句... 當我試圖通過使用tinyxml2::XMLDocument UserList解析我的XMLText保存的XML文件在運行程序後將爲空。這意味着在嘗試執行此操作時,原始XML文檔內容以及新分析的子樹都不會保存。這個事實使我使用第二個tinyxml2::XMLDocument TestParse。現在XML文件被保存,包含它的原始內容,但解析後的子樹仍然缺失......非常感謝您提供任何解決方案/幫助/建議。

回答

1

TinyXML-2爲存儲在XMLDocument中的內存池中的節點(XMLNode)分配內存。這修復了TinyXML-1中存在的內存碎片問題。

副作用是元素不能從一個XMLDocument移動到另一個。他們只能被複制。令人遺憾的是,TinyXML-2目前不支持深拷貝(樹拷貝),所以不能做你想要的。 (儘管在github網站上請求了深層副本)。

順便說一下,我期望您寫的代碼能夠聲明(在調試模式下)或崩潰,因爲myNewUser與UserList存在不同的內存池。

1

我用TinyXML-2的XMLVisitor編寫了一個深層複製函數。希望這對你有用:

#include <stack> 
#include "tinyxml2.h" 
using namespace tinyxml2; 
class MyXMLVisitor: public XMLVisitor 
{ 
public: 
    MyXMLVisitor(XMLDocument *doc) 
     : m_doc(doc) 
    { 
    } 

    virtual bool VisitEnter (const XMLElement &el, const XMLAttribute *attr) 
    { 
     XMLElement *new_el = m_doc->NewElement(el.Name()); 
     m_elementStack.push(new_el); 
     return true; 
    } 

    virtual bool Visit(const XMLText &txt) 
    { 
     m_elementStack.top()->SetText(txt.Value()); 
     return true; 
    } 

    virtual bool VisitExit (const XMLElement &el) 
    { 
     XMLElement *top_el = m_elementStack.top(); 
     m_elementStack.pop(); 
     if (m_elementStack.empty()) { 
      m_element = top_el; 
      return false; 
     } 
     else { 
      m_elementStack.top()->InsertEndChild(top_el); 
      return true; 
     } 
    } 


    std::stack<XMLElement*> m_elementStack; 
    XMLDocument *m_doc; 
    XMLElement *m_element; 
}; 


XMLElement* DeepCopyElement(XMLDocument &doc, const XMLElement *el) 
{ 
    MyXMLVisitor my_visitor(&doc); 
    el->Accept(&my_visitor); 
    return my_visitor.m_element; 
} 

int main(int argc, char* argv[]) 
{ 
    XMLDocument doc; 
    doc.LoadFile("test.xml"); 

    XMLElement *modulesElement = doc.FirstChildElement("modules"); 
    XMLElement *moduleElement = modulesElement->FirstChildElement("module"); 
    modulesElement->InsertEndChild(DeepCopyElement(doc, moduleElement)); 

    doc.SaveFile("test_out.xml"); 
    return 0; 
} 
+0

非常感謝你的回覆。但對於我的情況來說,有點太晚了,那時我自己找到了一個解決方法(不使用tinyxml)。這個解決方案雖然可以幫助別人 – Dino 2015-07-30 11:09:54