2014-09-02 4 views
0

Мне не разрешили создать новый тег 'tinyxml2', поэтому я использую тег 'tinyxml', однако я использую 'tinyxml2'!Вставка поддерева из текста в существующий файл XML с использованием tinyxml2

Я пытаюсь вставить элемент поддерева в существующий файл XML. Моя проблема в том, что после запуска программы и проверки XML-файла поддерево просто не существует в документе. В исходном коде я также проверяю ошибки при загрузке и сохранении файла, поэтому нет проблем с этими функциями, они работают правильно. Я пробовал несколько разных подходов, а также добавление одного элемента с помощью функции UserList.NewElement(*name*) также отлично работает. Теперь я хочу, чтобы вставить целое поддерево из текстовой переменной ...

Мой последний подход выглядит следующим образом (упрощенно без проверки LoadFile и SaveFile):

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

Кстати ... When Я попытался разобрать мой XMLText с помощью tinyxml2::XMLDocument UserList сохраненный файл XML будет пуст после запуска программы. Это означает, что ни один исходный документ XML-документа, ни недавно обработанное поддерево не будут сохранены при попытке сделать это. Этот факт заставил меня использовать второй tinyxml2::XMLDocument TestParse. Теперь файл XML сохраняется с его исходным контентом, однако разборное поддерево по-прежнему отсутствует ... большое спасибо за любое решение/помощь/совет.

ответ

1

TinyXML-2 выделяет память для своих узлов (XMLNode) в пулах памяти, хранящихся в XMLDocument. Это устраняет проблемы фрагментации памяти, присутствующие в TinyXML-1.

Побочным эффектом является то, что элементы не могут перемещаться из одного документа XMLDocument в другой. Их можно копировать только. К сожалению, TinyXML-2 в настоящее время не поддерживает глубокие копии (копии деревьев), поэтому не может делать то, что вы хотите. (Хотя глубокая копия запрашивается на сайте github.)

Я бы ожидал, что код, который вы написали, чтобы утверждать (в режиме отладки) или сбой, кстати, поскольку myNewUser находится в другом пуле памяти из UserList.

1

Я написал функцию глубокой копии, используя XMLVisitor TinyXML-2. Надеемся, это вам будет удобно:

#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