【问题标题】:Incorrect order of attributes in Qt XMLQt XML 中的属性顺序不正确
【发布时间】:2014-02-27 10:21:54
【问题描述】:

我有以下代码:

element.clear();
element.setTagName("accountpoint");
element.setAttribute("code", QString(ID_CONST)+serial);
element.setAttribute("name", QString());
element.setAttribute("serial", serial);

QFile file(filename);
file.open(QIODevice::ReadWrite);
QTextStream stream(&file);
doc.save(stream, 4);

我想我会得到一个类似的 XML:

<accountpoint code="4871583314750580" name="" serial="14750580">

但我有:

<accountpoint serial="14750580" code="4871583314750580" name="">

为什么?

附:是的,当然,在 XML 文档中没关系,但我想获得正确的属性顺序。

【问题讨论】:

  • Qt 在保存到流时不保证属性的顺序。您应该改为 QXmlStreamWriter - 使用它您可以控制属性的顺序。无论如何,QtXML 在 QT5 中已被弃用
  • 如你所说,顺序无关紧要,所以没有正确/错误、正确/错误的属性顺序。 (但正如 Alex 所说,QXmlStreamWriter 会保留它们)
  • @alextelishev,感谢您的回答!我正在使用 Qt 4.8(我正在等待 Max Schlee 撰写的关于 Qt 5.2 的书,他在 vkontakte 页面上承诺过)

标签: c++ xml qt qtxml


【解决方案1】:

我在尝试将 xml 设置数据存储在 git 中时遇到了这个问题。在这种情况下(为了获得合理的差异),每次使用相同的属性排序来存储 xml 是很重要的。代码库已有数年历史,使用已弃用的 Qt Xml 而不是较新的 QXmlStreamWriter

设置 QT_HASH_SEED 环境变量的技巧(来自@MrEricSir 的回答)在这种情况下效果很好。但是,也可以直接在代码中完成,如下例所示:

qSetGlobalQHashSeed(0); // set a fixed hash value

QDomDocument doc = QDomDocument(); 
// add stuff to doc...
// ...

// save doc to file:
QFile file(filename);
QTextStream stream(&file);
stream << doc.toString(4);
file.close();

// reset hash seed with new random value.
qSetGlobalQHashSeed(-1);

这样,您的应用程序的其余部分就可以像以前一样工作,从而避免暴露于algorithmic complexity attacks

【讨论】:

  • 此功能是在 Qt 5.6 中引入的
  • 请注意:“从 Qt 5.10 及更高版本开始,唯一允许的值是 0 和 -1。” (qSetGlobalQHashSeed 文档)
【解决方案2】:

我意识到这是对一个老问题的部分回答,但如果您只想让属性的顺序一致每次有办法在 Qt5 中实现这一点。

排序不一致的原因是属性存储在哈希映射中。默认情况下,每次您的应用程序开始防范某些类型的 DDOS 攻击时,QHash 都会随机化其种子。但是有a workaround

默认情况下启用 QHash 的随机化。虽然 程序不应该依赖于特定的 QHash 排序,可能有 是您暂时需要确定性行为的情况,例如 用于调试或回归测试。要禁用随机化, 定义环境变量QT_HASH_SEED。那里面的内容 变量,解释为十进制值,将用作种子 qHash()。

因此,您需要做的就是设置一个名为 QT_HASH_SEED 的环境变量,该变量具有一致的值。例如,您可以在 Qt Creator 的 Projects 选项卡中进行设置:

这可能会或可能不会解决您的问题,但它对于单元测试非常方便。

【讨论】:

    【解决方案3】:

    不存在 XML 属性的“正确”顺序。标准的 XML 实现不关心它,他们不关心它,这是正确的。

    人类可读性是担心属性顺序的唯一原因。如果您想编写人类可读的 XML,您可能需要编写自己的代码。

    【讨论】:

    • 但是有一个叫做Canonical XML的东西,其中指定了顺序并且是有原因的。您认为人类可读性是唯一的原因是错误的。您是否尝试过将 QtXML 中的文件存储在源代码控制系统中并尝试区分/合并它?真是一团糟,就是这样!
    【解决方案4】:

    请使用 QXmlStreamWriter 以所需属性的确定顺序写入文件。

    由于 QT_HASH_SEED 的设置值并没有给出您尝试写入的属性的确切顺序。并且 QT_HASH_SEED 的值对于低于 QT5.10 的版本是不可能的。

    最好的解决方案是 QXMLStreamWriter 下面的代码:

    QString destPath = "C:/XYZ/myXLM.xml";
        QFile modelConfig(destPath);
        if (!modelConfig.open(QIODevice::WriteOnly)) {
            return 0;
        }
    
        QXmlStreamWriter xml(&modelConfig);
        for(int i =0;i < 10;i++)
        {
            xml.writeStartElement("ModelsSimpaConfig");
            xml.writeAttribute("Name", "NAME" + QString::number(i));
            xml.writeAttribute("ID", "ID" + QString::number(i));
            xml.writeAttribute("IDPlus", "IDPLUS" + QString::number(i));
            xml.writeAttribute("Xyz", "XYZ" + QString::number(i));
            xml.writeAttribute("Abc","ABC" + QString::number(i));
    
            xml.writeEndElement();
            xml.writeEndDocument();
        }
    
    
        modelConfig.close();
        qDebug() << "Writing is done";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-14
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 2013-07-12
      • 2014-12-18
      • 2013-04-08
      相关资源
      最近更新 更多