问题
I have the following code:
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);
I thought I will get an XML like:
<accountpoint code="4871583314750580" name="" serial="14750580">
But I have:
<accountpoint serial="14750580" code="4871583314750580" name="">
Why?
P.S. Yes, of course, in XML document it does not matter, but I want to get the right order of attributes.
回答1:
I realize this is a partial answer to an old question, but if you just want the order of the attributes to be consistent every time there's a way to achieve this in Qt5.
The reason for the inconsistent ordering is that the attributes are stored in a hash map. By default QHash randomizes its seed every time your application starts to guard against certain types of DDOS attacks. But there is a workaround:
This randomization of QHash is enabled by default. Even though programs should never depend on a particular QHash ordering, there may be situations where you temporarily need deterministic behavior, e.g. for debugging or regression testing. To disable the randomization, define the environment variable QT_HASH_SEED. The contents of that variable, interpreted as a decimal value, will be used as the seed for qHash().
So all you need to do is set an environment variable named QT_HASH_SEED that has a consistent value. For example you can set this in Qt Creator in the Projects tab:
This may or may not solve your problem, but it's super handy for unit testing.
回答2:
I ran into this issue when trying to store xml setting data in git. In this case (in order to get a sane diff) it is important to store the xml using the same attribute ordering each time. The code base was several years old, using the deprecated Qt Xml instead of the newer QXmlStreamWriter.
The trick of setting the QT_HASH_SEED environment variable (from @MrEricSir's answer) works well in this case. However, it can also be done directly in code, like in this example:
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);
This way, the rest of your application works as before, thus avoiding exposure to algorithmic complexity attacks.
回答3:
There is no such thing as a "right" order of XML attributes. Standard XML implementations can't care about it, and they don't, and rightly so.
Human readability is about the only reason to worry about attribute order. If you want to write human-readable XML, you may need to roll your own code.
回答4:
Please use QXmlStreamWriter to write files in the deterministic order of attributes needed.
As the setting value of QT_HASH_SEED does not give exact order of attributes you trying to write. and Also setting the value of QT_HASH_SEED is not possible for the Below QT5.10 version.
Best Solution is QXMLStreamWriter below code:
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";
来源:https://stackoverflow.com/questions/21535707/incorrect-order-of-attributes-in-qt-xml