0

我不允许创建新标签“tinyxml2”,这就是我使用标签“tinyxml”的原因,但我使用的是“tinyxml2”!

我正在尝试将子树元素插入现有的 XML 文件。我的问题是,在运行程序并检查 XML 文件后,文档中根本不存在子树。在原始代码中,我还在加载和保存文件时检查错误,因此这些功能没有问题,它们工作正常。UserList.NewElement(*name*)我尝试了几种不同的方法,并且使用-function添加单个元素也可以正常工作。现在我想从一个文本变量中插入一个完整的子树......

我的最新方法如​​下所示(简化后不检查LoadFileand 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 文件包含它的原始内容,但是解析的子树仍然丢失......非常感谢您的任何解决方案/帮助/建议。

4

2 回答 2

1

TinyXML-2 在存储在 XMLDocument 中的内存池中为其节点 (XMLNode) 分配内存。这修复了 TinyXML-1 中存在的内存碎片问题。

副作用是元素不能从一个 XMLDocument 移动到另一个。它们只能被复制。遗憾的是,TinyXML-2 目前不支持深拷贝(树拷贝),所以不能为所欲为。(尽管在 github 站点上要求提供深层副本。)

顺便说一句,我希望您编写的代码能够断言(在调试模式下)或崩溃,因为 myNewUser 与 UserList 位于不同的内存池中。

于 2014-09-10T18:28:37.593 回答
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;
}
于 2015-07-13T22:03:12.700 回答