6

次のコードがあります。

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="">

なんで?

PS はい、もちろん、XML ドキュメントでは問題ありませんが、属性の正しい順序を取得したいと考えています。

4

4 に答える 4

7

xml設定データをgitに保存しようとしたときに、この問題に遭遇しました。この場合 (正常な差分を取得するために)、毎回同じ属性の順序付けを使用して xml を保存することが重要です。コードベースは数年前のもので、新しいQXmlStreamWriterの代わりに非推奨のQt Xmlを使用していました。

この場合、QT_HASH_SEED 環境変数 (@MrEricSir の回答から) を設定するトリックがうまく機能します。ただし、次の例のように、コードで直接実行することもできます。

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

このようにして、アプリケーションの残りの部分は以前と同じように機能するため、アルゴリズムの複雑さの攻撃にさらされることを回避できます。

于 2016-10-10T07:35:45.657 に答える
6

これは古い質問に対する部分的な回答であることは理解していますが、属性の順序を毎回一貫させたい場合は、Qt5 でこれを実現する方法があります。

順序付けに一貫性がないのは、属性がハッシュ マップに格納されているためです。デフォルトでは、QHash は、アプリケーションが特定の種類の DDOS 攻撃に対する保護を開始するたびにシードをランダム化します。しかし、回避策があります:

この QHash のランダム化はデフォルトで有効になっています。プログラムは特定の QHash の順序に依存するべきではありませんが、デバッグや回帰テストなど、一時的に確定的な動作が必要になる場合があります。ランダム化を無効にするには、環境変数QT_HASH_SEEDを定義します。10 進値として解釈されるその変数の内容は、qHash() のシードとして使用されます。

したがって、一貫した値を持つ QT_HASH_SEED という名前の環境変数を設定するだけです。たとえば、Qt Creator の [プロジェクト] タブでこれを設定できます。

Qt Creator の [プロジェクト] タブの [実行] 設定で QT_HASH_SEED を設定する場所

これで問題が解決する場合としない場合がありますが、単体テストには非常に便利です。

于 2015-05-07T04:03:50.787 に答える
0

QXmlStreamWriter を使用して、必要な属性の決定論的な順序でファイルを書き込んでください。

QT_HASH_SEEDの設定値は、書き込もうとしている属性の正確な順序を示していないためです。また、QT5.10 未満のバージョンでは、QT_HASH_SEED の値を設定することはできません。

最良の解決策は、コードの下の QXMLStreamWriter です。

QString destPath = "C:/XYZ/myXLM.xml";
    QFile modelConfig(destPath);
    if (!modelConfig.open(QIODevice::WriteOnly)) {
        return 0;
    }

    QXmlStreamWriter xml(&modelConfig);
    for(int i =0;i < 10;i++)
    {
        xml.writeStartElement("ModelsSimpaConfig");
        xml.writeAttribute("Name", "NAME" + QString::number(i));
        xml.writeAttribute("ID", "ID" + QString::number(i));
        xml.writeAttribute("IDPlus", "IDPLUS" + QString::number(i));
        xml.writeAttribute("Xyz", "XYZ" + QString::number(i));
        xml.writeAttribute("Abc","ABC" + QString::number(i));

        xml.writeEndElement();
        xml.writeEndDocument();
    }


    modelConfig.close();
    qDebug() << "Writing is done";
于 2019-11-12T08:54:14.853 に答える