Вставка поддерева из текста в существующий 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 сохранен с его оригинальным содержимым, однако проанализированное поддерево все еще отсутствует … большое спасибо за любое решение / помощь / совет.

0

Решение

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;
}
1

По вопросам рекламы [email protected]