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 <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[])
|
||||
{
|
||||
Q_INIT_RESOURCE(tapeicon);
|
||||
|
@ -47,8 +43,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
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
|
||||
InitHighDpiScaling(argc, argv);
|
||||
#endif //Q_OS_MAC
|
||||
|
|
|
@ -34,10 +34,6 @@
|
|||
#include <QMessageBox> // For QT_REQUIRE_VERSION
|
||||
#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[])
|
||||
|
@ -52,8 +48,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
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
|
||||
qRegisterMetaTypeStreamOperators<VPieceNode>("VPieceNode");
|
||||
|
||||
|
|
|
@ -63,6 +63,66 @@
|
|||
#include <QXmlSchema>
|
||||
#include <QXmlSchemaValidator>
|
||||
#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
|
||||
class MessageHandler : public QAbstractMessageHandler
|
||||
|
@ -202,6 +262,37 @@ bool VDomDocument::find(const QDomElement &node, const QString& id)
|
|||
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?
|
||||
|
@ -649,10 +740,17 @@ bool VDomDocument::SaveDocument(const QString &fileName, QString &error) const
|
|||
// cppcheck-suppress ConfigurationNotChecked
|
||||
if (file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
// See issue #666. QDomDocument produces random attribute order.
|
||||
const int indent = 4;
|
||||
QTextStream out(&file);
|
||||
out.setCodec("UTF-8");
|
||||
save(out, indent);
|
||||
if (not SaveCanonicalXML(&file, indent, error))
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,8 @@ private:
|
|||
QHash<QString, QDomElement> map;
|
||||
|
||||
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