У меня есть следующий код:
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-документе это не имеет значения, но я хочу получить правильный порядок атрибутов.
Я понимаю, что это частичный ответ на старый вопрос, но если вы просто хотите, чтобы порядок атрибутов был последовательный каждый раз есть способ добиться этого в Qt5.
Причина несогласованного упорядочения заключается в том, что атрибуты хранятся в хэш-карте. По умолчанию QHash рандомизирует свое начальное число каждый раз, когда ваше приложение начинает защищаться от определенных типов DDOS-атак. Но есть обходной путь:
Эта рандомизация QHash включена по умолчанию. Даже если
программы никогда не должны зависеть от определенного порядка QHash, может
быть ситуациями, когда вам временно необходимо детерминированное поведение, например,
для отладки или регрессионного тестирования. Чтобы отключить рандомизацию,
определить переменную среды QT_HASH_SEED. Содержание этого
переменная, интерпретируемая как десятичное значение, будет использоваться в качестве начального числа для
QHash ().
Поэтому все, что вам нужно сделать, это установить переменную среды с именем QT_HASH_SEED, которая имеет непротиворечивое значение. Например, вы можете установить это в Qt Creator на вкладке Projects:
Это может или не может решить вашу проблему, но это очень удобно для модульного тестирования.
Я столкнулся с этой проблемой при попытке сохранить данные настроек xml в git. В этом случае (чтобы получить вменяемый diff) важно хранить 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);
Таким образом, остальная часть вашего приложения работает как прежде, что позволяет избежать воздействия атаки на алгоритмическую сложность.
Не существует такого понятия, как «правильный» порядок атрибутов XML. Стандартные реализации XML не могут заботиться об этом, и они не заботятся, и это правильно.
Человеческая читаемость — единственная причина для беспокойства о порядке следования атрибутов. Если вы хотите написать понятный человеку XML, вам может потребоваться развернуть собственный код.