Resolved issue #666. QDomDocument produces random attribute order.
--HG-- branch : release
This commit is contained in:
parent
b4106f8e5a
commit
6c047b140d
|
@ -33,10 +33,6 @@
|
||||||
#include <QMessageBox> // For QT_REQUIRE_VERSION
|
#include <QMessageBox> // For QT_REQUIRE_VERSION
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
// Lock producing random attribute order in XML
|
|
||||||
// https://stackoverflow.com/questions/27378143/qt-5-produce-random-attribute-order-in-xml
|
|
||||||
extern Q_CORE_EXPORT QBasicAtomicInt qt_qhash_seed;
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Q_INIT_RESOURCE(tapeicon);
|
Q_INIT_RESOURCE(tapeicon);
|
||||||
|
@ -47,8 +43,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
QT_REQUIRE_VERSION(argc, argv, "5.2.0")
|
QT_REQUIRE_VERSION(argc, argv, "5.2.0")
|
||||||
|
|
||||||
qt_qhash_seed.store(0); // Lock producing random attribute order in XML
|
|
||||||
|
|
||||||
#ifndef Q_OS_MAC // supports natively
|
#ifndef Q_OS_MAC // supports natively
|
||||||
InitHighDpiScaling(argc, argv);
|
InitHighDpiScaling(argc, argv);
|
||||||
#endif //Q_OS_MAC
|
#endif //Q_OS_MAC
|
||||||
|
|
|
@ -34,10 +34,6 @@
|
||||||
#include <QMessageBox> // For QT_REQUIRE_VERSION
|
#include <QMessageBox> // For QT_REQUIRE_VERSION
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
// Lock producing random attribute order in XML
|
|
||||||
// https://stackoverflow.com/questions/27378143/qt-5-produce-random-attribute-order-in-xml
|
|
||||||
extern Q_CORE_EXPORT QBasicAtomicInt qt_qhash_seed;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -52,8 +48,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
QT_REQUIRE_VERSION(argc, argv, "5.2.0")
|
QT_REQUIRE_VERSION(argc, argv, "5.2.0")
|
||||||
|
|
||||||
qt_qhash_seed.store(0); // Lock producing random attribute order in XML
|
|
||||||
|
|
||||||
// Need to internally move a node inside a piece main path
|
// Need to internally move a node inside a piece main path
|
||||||
qRegisterMetaTypeStreamOperators<VPieceNode>("VPieceNode");
|
qRegisterMetaTypeStreamOperators<VPieceNode>("VPieceNode");
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,66 @@
|
||||||
#include <QXmlSchema>
|
#include <QXmlSchema>
|
||||||
#include <QXmlSchemaValidator>
|
#include <QXmlSchemaValidator>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
#include <QXmlStreamWriter>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void SaveNodeCanonically(QXmlStreamWriter &stream, const QDomNode &domNode)
|
||||||
|
{
|
||||||
|
if (stream.hasError())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (domNode.isElement())
|
||||||
|
{
|
||||||
|
const QDomElement domElement = domNode.toElement();
|
||||||
|
if (not domElement.isNull())
|
||||||
|
{
|
||||||
|
stream.writeStartElement(domElement.tagName());
|
||||||
|
|
||||||
|
if (domElement.hasAttributes())
|
||||||
|
{
|
||||||
|
QMap<QString, QString> attributes;
|
||||||
|
const QDomNamedNodeMap attributeMap = domElement.attributes();
|
||||||
|
for (int i = 0; i < attributeMap.count(); ++i)
|
||||||
|
{
|
||||||
|
const QDomNode attribute = attributeMap.item(i);
|
||||||
|
attributes.insert(attribute.nodeName(), attribute.nodeValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, QString>::const_iterator i = attributes.constBegin();
|
||||||
|
while (i != attributes.constEnd())
|
||||||
|
{
|
||||||
|
stream.writeAttribute(i.key(), i.value());
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (domElement.hasChildNodes())
|
||||||
|
{
|
||||||
|
QDomNode elementChild = domElement.firstChild();
|
||||||
|
while (not elementChild.isNull())
|
||||||
|
{
|
||||||
|
SaveNodeCanonically(stream, elementChild);
|
||||||
|
elementChild = elementChild.nextSibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeEndElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (domNode.isComment())
|
||||||
|
{
|
||||||
|
stream.writeComment(domNode.nodeValue());
|
||||||
|
}
|
||||||
|
else if (domNode.isText())
|
||||||
|
{
|
||||||
|
stream.writeCharacters(domNode.nodeValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//This class need for validation pattern file using XSD shema
|
//This class need for validation pattern file using XSD shema
|
||||||
class MessageHandler : public QAbstractMessageHandler
|
class MessageHandler : public QAbstractMessageHandler
|
||||||
|
@ -202,6 +262,37 @@ bool VDomDocument::find(const QDomElement &node, const QString& id)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool VDomDocument::SaveCanonicalXML(QIODevice *file, int indent, QString &error) const
|
||||||
|
{
|
||||||
|
SCASSERT(file != nullptr)
|
||||||
|
|
||||||
|
QXmlStreamWriter stream(file);
|
||||||
|
stream.setAutoFormatting(true);
|
||||||
|
stream.setAutoFormattingIndent(indent);
|
||||||
|
stream.writeStartDocument();
|
||||||
|
|
||||||
|
QDomNode root = documentElement();
|
||||||
|
while (not root.isNull())
|
||||||
|
{
|
||||||
|
SaveNodeCanonically(stream, root);
|
||||||
|
if (stream.hasError())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
root = root.nextSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeEndDocument();
|
||||||
|
|
||||||
|
if (stream.hasError())
|
||||||
|
{
|
||||||
|
error = tr("Fail to write Canonical XML.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* @brief Returns the long long value of the given attribute. RENAME: GetParameterLongLong?
|
* @brief Returns the long long value of the given attribute. RENAME: GetParameterLongLong?
|
||||||
|
@ -649,10 +740,17 @@ bool VDomDocument::SaveDocument(const QString &fileName, QString &error) const
|
||||||
// cppcheck-suppress ConfigurationNotChecked
|
// cppcheck-suppress ConfigurationNotChecked
|
||||||
if (file.open(QIODevice::WriteOnly))
|
if (file.open(QIODevice::WriteOnly))
|
||||||
{
|
{
|
||||||
|
// See issue #666. QDomDocument produces random attribute order.
|
||||||
const int indent = 4;
|
const int indent = 4;
|
||||||
QTextStream out(&file);
|
if (not SaveCanonicalXML(&file, indent, error))
|
||||||
out.setCodec("UTF-8");
|
{
|
||||||
save(out, indent);
|
return false;
|
||||||
|
}
|
||||||
|
// Left these strings in case we will need them for testing purposes
|
||||||
|
// QTextStream out(&file);
|
||||||
|
// out.setCodec("UTF-8");
|
||||||
|
// save(out, indent);
|
||||||
|
|
||||||
success = file.commit();
|
success = file.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,8 @@ private:
|
||||||
QHash<QString, QDomElement> map;
|
QHash<QString, QDomElement> map;
|
||||||
|
|
||||||
bool find(const QDomElement &node, const QString& id);
|
bool find(const QDomElement &node, const QString& id);
|
||||||
|
|
||||||
|
bool SaveCanonicalXML(QIODevice *file, int indent, QString &error) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user