【问题标题】:How to save changes to XML file using TinyXML?如何使用 TinyXML 保存对 XML 文件的更改?
【发布时间】:2012-03-18 01:11:13
【问题描述】:

我正在处理一个项目,该项目需要我将一些数据从 XML 文件加载到 GUI。 GUI 允许用户对数据进行一些更改。我想要做的是将这些更改保存回 XML 文件。

我知道可以重写整个文件,但是文件非常大,而且不是文件中的所有数据都被更改甚至在我的程序中使用。

这是我第一个使用 TinyXML 和 C++ Builder 的项目。我只是在寻找一些关于我应该如何处理这个问题的建议。

【问题讨论】:

  • TinyXML tutorial 将是使用库本身的一个很好的起点。这与问题无关,但是AFAIK,TinyXML 是一个DOM 解析器。如果您只需要处理部分 XML 文件,SAX 解析器会更快。
  • 我很快用谷歌搜索了 SAX 解析器,看看它是关于什么的,它似乎可以工作。你对开源有什么建议吗?
  • 快速访问 Google 将我带到 Expat 解析器。它同时支持 DOM 和 SAX。 Google 还返回了this C/C++ 解析库列表,或许可以作为参考。
  • 谢谢你会更深入地研究它

标签: c++ xml-parsing c++builder tinyxml


【解决方案1】:

除非您确定新文本的大小与旧文本完全相同,否则仅重写文本文件的一部分通常不是一个好主意。有些文件格式可以进行零碎替换。 XML 不是其中之一。至少在一般情况下不会。

在文件中间插入数据,从而将其余部分向下移动,基本上相当于加载文件的其余部分,使文件变大,然后将其写回。因此,您也可以加载整个文件,进行修改,然后再次保存。您的代码会更简单,而且可能不会慢很多。

不,SAX 解析器在这里帮不了您。它允许您流式读取(尽管我建议使用拉式解析器而不是推式解析器),但这不允许您将数据插入文件中。我所知道的大多数 XML 解析器通常不支持这一点。他们可以写入数据,但是写入和非破坏性插入是两个不同的东西。

【讨论】:

  • 我认为你的建议是迄今为止最有意义的。就像我在回应悲伤的回答时所说的那样,我需要确保我选择保存 xml 的方法不会损坏文件中未用于我的程序的其他部分。并且通过将文件的其他部分向下或向上或 w.e 移动,似乎损坏它所保存的数据的可能性最小。谢谢
  • @livelaughlove:在没有真正理解 XML 格式的程序的情况下更改 XML 数据总是比使用理解 XML 的程序更危险。 TinyXML(或任何 XML 解析器)将确保您正在编写 XML;一些非 XML 插入工具不会。只需在错误的位置添加一个关闭标记,就可以完全破坏 XML 文件的格式。
  • 我不太担心 xml 的实际格式。我担心的是(如果这看起来完全愚蠢,请原谅我,对于这个 tinyxml 和 xml 的东西仍然是新的)是否有机会说更改的数据覆盖 XML 文件的其他部分或更改 XML 的其他部分的数据文件本身。根据我对您的解释的理解,我基本上只是将 xml 的其他部分作为一个整体转移并为更改的数据腾出空间,但并没有真正更改其他部分的数据。
【解决方案2】:

TinyXml 可以让你做你想做的事,而不会损坏文件内容(只要其有效的 xml)。我刚刚检查了这个,所以我很确定。显然,您必须知道并准确地知道要编辑哪些属性和标签,但是即使在您编辑的标签内,您也可以添加/编辑标签而不会影响现有的属性/标签/cmets。您需要一段时间才能习惯这种结构,但这绝对是可能的。

你必须知道xml的结构!

TiXmlDocument doc("filepath"); //will open your document

if (!doc.LoadFile()) //you do have to open the whole file
{
    cout<<"No XML structure found"<<endl;
    return; // exit function don't load anything
}
TiXmlElement *root = doc.RootElement(); //pointer to root element

现在您可以使用此指针和命令,例如:

root->FirstChild("tageone")->ToElement();
tageone->SetDoubleAttribute("attribute", value);

改变东西。

抱歉,解释的太仓促了,但您需要通读一下文档才能掌握其中的窍门。

干杯

【讨论】:

    【解决方案3】:

    更新

    正如我在评论中所说,我认为插入文件中间不会更好。但是,如果您需要/想要额外的安全性,我建议您执行两个额外的步骤:

    • 在所有重要步骤中对 xml 文件执行完整性检查。这可以是您确保正在阅读的文件确实是您需要的任何内容。
    • 在保存之前计算整个文件内容的校验和,然后检查。这不一定需要是CRC,我只是将函数命名为calculate_crc()。任何可以让您验证数据完整性的东西都是好的。

    我会大致如下(伪代码):

    TiXmlDocument doc( "demo.xml" );
    doc.LoadFile();
    
    perform_sanitycheck(doc);
    
    //  do whatever you need to change
    
    perform_sanitycheck(doc);
    unsigned int crc = calculate_crc(doc);
    
    doc.SaveFile("temp_name.xml");  // save the file under another name
    
    TiXmlDocument doc2( "temp_name.xml" );
    perform_sanitycheck(doc2);
    if(verify_crc(doc, crc))
    {
        delete_file("demo.xml");
        rename_file("temp_name.xml", "demo.xml");
    }
    

    必要时,完整性检查会采取适当的措施。您需要将两个函数 delete_file()rename_file() 替换为您的环境的 API 或库函数。

    函数calculate_crc()verify_crc() 可以专门用于检查您需要更改的部分。

    【讨论】:

    • 文件大小并不是真正的问题。 xml 文件包含很多重要信息。我只将文件的一部分用于我的程序,并且只对那部分进行更改。因此,如果我使用 SaveFile,它是否有可能完全损坏 xml 文件的其他部分?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多