Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect order of attributes in Qt XML

Tags:

c++

xml

qt

qtxml

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.

like image 826
MastAKK Avatar asked Feb 03 '14 19:02

MastAKK


People also ask

What is the use of int qxmlattributes index?

int QXmlAttributes:: index (const QString & uri, const QString & localPart) const This is an overloaded function. Looks up the index of an attribute by a namespace name. uri specifies the namespace URI, or an empty string if the name has no namespace URI. localPart specifies the attribute's local name.

What is qxmlattributes class used for?

The QXmlAttributes class provides XML attributes. More... This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code.

What does append do in void void qxmlattributes?

void QXmlAttributes:: append (const QString & qName, const QString & uri, const QString & localPart, const QString & value) Appends a new attribute entry to the list of attributes.

What is the qualified name of the attribute in the list?

The qualified name of the attribute is qName, the namespace URI is uri and the local name is localPart. The value of the attribute is value. See also qName (), uri (), localName (), and value (). Clears the list of attributes. See also append (). Returns the number of attributes in the list. This function is equivalent to length ().


2 Answers

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(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);

This way, the rest of your application works as before, thus avoiding exposure to algorithmic complexity attacks.

like image 73
Christian Askeland Avatar answered Oct 11 '22 04:10

Christian Askeland


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:

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

This may or may not solve your problem, but it's super handy for unit testing.

like image 41
MrEricSir Avatar answered Oct 11 '22 05:10

MrEricSir