xml - Qt 5 在 XML 中生成随机属性顺序

标签 xml qt random qt4 qt5

当从 Qt 4.8 切换到 Qt 5.x 时,您可能会注意到每次保存 XML 文档时它都会在文件中产生随机属性顺序。 以编程方式读取 XML 文档没有问题,因为在反序列化 XML 时允许以任何顺序存储属性。当您使用 GIT、SVN 等跟踪输出 XML 文件的更改时,这是一个问题 - 无法判断 XML 文件中的数据是否更改或属性结构是否更改。

是否可以在 Qt 5.x 中以与 Qt 4.8 中相同的方式生成 XML 文件?

最佳答案

我尝试使用哈希种子,但只有在您使用一台机器时它才能正常工作。如果在第一台机器上创建的文件在第二台机器上打开,即使我将哈希种子设置为相同的值,相同的代码也不会产生相同的顺序。所以,我决定寻找另一种解决方案。

我决定使用 QXmlStreamWriter类作为包装器。每次我保存 QDomDocument 时,我都会解析它并通过 QXmlStreamWriter 写入。这有助于我将 xml DOM 转换为 canonical form .

这是我使用的代码。也许有人会发现它很有用。

bool MyDomDocument::SaveCanonicalXML(QIODevice *file, int indent, QString &error) const
{
  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;
}

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

关于xml - Qt 5 在 XML 中生成随机属性顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27378143/

相关文章:

xml - 如何将 XML 中的特殊字符转换为 VBA 中的可读字符串?

sql - 在 SQL 中读取 XML 属性时返回 '0' INT

javascript - 搜索 XML 文件并使用 javascript 显示结果

c++ - 在 Mac 上检测 PDF 打印

c++ - 在哪里可以找到 Qt 库的开源小部件?

javascript - 如何在javascript中使用canvas绘制多个随机对象

xml - 当节点文本包含时xPath获取兄弟节点

qt - QML 应用程序窗口 : set minimum size to fit content

c++ - 通过构造函数错误地播种 Mersenne Twister

c++ - 使用快速英特尔随机生成器 (SSE2) 失败并出现堆栈...已损坏