我有以下代码:
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文档中它并不重要,但我想获得正确的属性顺序。
答案 0 :(得分:6)
我意识到这是对旧问题的部分答案,但是如果你只想让属性的顺序一致每次都有办法在Qt5中实现这一点。
排序不一致的原因是属性存储在哈希映射中。默认情况下,QHash会在每次应用程序开始防范某些类型的DDOS攻击时随机化其种子。但有a workaround:
默认情况下启用QHash的随机化。即使 程序不应该依赖于特定的QHash排序,也可能 是你暂时需要确定性行为的情况,例如: 用于调试或回归测试。要禁用随机化, 定义环境变量 QT_HASH_SEED 。那个内容 变量,解释为十进制值,将用作种子 qHash()。
所以你需要做的就是设置一个名为QT_HASH_SEED的环境变量,它具有一致的值。例如,您可以在Qt Creator中的Projects选项卡中设置它:
这可能会或可能不会解决您的问题,但它对于单元测试来说非常方便。
答案 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";