Qt XML中属性的顺序不正确

时间:2014-02-03 19:12:21

标签: c++ xml qt qtxml

我有以下代码:

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="">

为什么?

P.S。是的,当然,在XML文档中它并不重要,但我想获得正确的属性顺序。

4 个答案:

答案 0 :(得分:6)

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

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

  

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

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

Where to set QT_HASH_SEED in the Run settings in the Project tab in Qt Creator

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

答案 1 :(得分:3)

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

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

qSetGlobalQHashSeed(42); // 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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

由于 QT_HASH_SEED 的设置值未给出您尝试编写的属性的确切顺序。以下QT5.10版本也无法设置QT_HASH_SEED的值。

最佳解决方案是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";