【问题标题】:Inserting a subtree from text into an existing XML file using tinyxml2使用 tinyxml2 将文本中的子树插入现有 XML 文件
【发布时间】:2014-09-02 14:37:16
【问题描述】:

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

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

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

【问题讨论】:

    标签: c++ xml insert tinyxml subtree


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      我使用 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;
      }
      

      【讨论】:

      • 非常感谢您的回复。但是对于我的情况,它来得太晚了,当时我自己找到了一种解决方法(不使用 tinyxml)。这个解决方案可能会帮助其他人......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-22
      • 2014-06-17
      • 2021-03-14
      • 1970-01-01
      相关资源
      最近更新 更多