Вставка поддерева из текста в существующий файл XML с использованием tinyxml2

Мне не разрешили создать новый тег 'tinyxml2', поэтому я использую тег 'tinyxml', однако я использую '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*);

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


person Dino    schedule 02.09.2014    source источник


Ответы (2)


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

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

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

person grinliz    schedule 10.09.2014

Я написал функцию глубокого копирования, используя 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;
}
person kenny-liu    schedule 13.07.2015
comment
Спасибо вам большое за ваш ответ. Однако в моем случае это произошло слишком поздно, я сам нашел обходной путь в то время (не используя tinyxml). Это решение может помочь другим, хотя... - person Dino; 30.07.2015