次の等価性チェックアルゴリズムを思いつきました:
2 つのノードa
とb
が等しい場合、a >= b
とb>=a
bool compare( QDomElement element1, QDomElement element2 )
{
return ! lessThen(element1, element2) && !lessThen(element2, element1);
}
あとは紹介するだけです
比較アルゴリズム
ネイティブのQString
比較機能を使用するようになりました
まず、一般的なアプローチでは、QDomElement
s だけでなくQDomNode
Dom 内のすべてを比較する必要があります。
- なら
a.nodeType < b.nodeType
、a < b
- そうでなければ、もし
a.nodeName < b.nodeName
、a < b
- そうでなければ、もし
a.children.size() < b.children().size()
、a < b
- それ以外の場合
a.children().size() ==0 && b.children().size() ==0
は、比較しnodeValue()
ます。このアプローチは、属性ノードとテキスト ノードの両方で機能することに注意してください。QDomElement 自体にはありませんnodeValue
。要素内に記述されたテキストの場合、要素にはテキスト型の子ノードがあります。そのため、element.nodeValue()
呼び出しは常に null 文字列を返します。
lessThen
それ以外の場合は、 compare 関数を使用して、指定されたノードのすべての子を並べ替えます。
- 次に、すべての子が
c
に属し、a
にd
属していることを確認しb
ます。
- なら
d > c
、a > b
- なら
c < d
、a < b
- それ以外の場合 ( ) 次のと
c==d
の比較を続行します。c
d
- すべて
c
が に等しい場合d
、a == b
、そして明らかa < b
に間違っています。
このアルゴリズムを実装するコード:
QList<QDomNode> getChildElements(const QDomNode& e)
{
QList<QDomNode> r;
for (int k = 0; k < e.childNodes().size(); ++k) {
QDomNode n = e.childNodes().at(k);
r << n;
}
return r;
}
bool lessThen( QDomNode element1, QDomNode element2 )
{
if (element1.nodeType() != element2.nodeType()) {
return element1.nodeType() < element1.nodeType();
}
QString tag1 = element1.nodeName() ;
QString tag2 = element2.nodeName() ;
//qDebug() << tag1 <<tag2;
if ( tag1 != tag2 )
return tag1 < tag2;
QList<QDomNode> elts1 = getChildElements(element1);
QList<QDomNode> elts2 = getChildElements(element2);
QString value1, value2 ;
if(elts1.size() != elts2.size())
return elts2.size() < elts1.size() ;
if(elts1.size() == 0)
{
value1 = element1.nodeValue();
value2 = element2.nodeValue();
//qDebug() <<value1 << value2 << (value1 < value2);
return value1 < value2;
}
qSort(elts1.begin(), elts1.end(), lessThen);
qSort(elts2.begin(), elts2.end(), lessThen);
//qDebug() << "comparing sorted lists";
for(int k = 0; k < elts1.size(); ++k) {
if (!lessThen(elts1[k], elts2[k])) {
if (lessThen(elts2[k], elts1[k])) {
//qDebug() << "false!";
return false;
}
}else {
//qDebug() << "true!";
return true;
}
}
return false;
}
bool compare( QDomElement element1, QDomElement element2 )
{
return ! lessThen(element1, element2) && !lessThen(element2, element1);
}
比較アルゴリズムは非常に複雑であることに注意してください。2MBのxmlファイルを処理するのに約10分かかりました(xml-should-be-equal-to-itselfテストあり)
可能なテスト
フォーマット:
description (desired result)
<xml1>
<xml2>
result
テスト:
different order (true)
"<r>
<a>x</a>
<a>y</a>
</r>
"
"<r>
<a>y</a>
<a>x</a>
</r>
"
true
different text (false)
"<a>x</a>
"
"<a>y</a>
"
false
different text with structure (false)
"<a>x<b/>ddcd</a>
"
"<a>y<b/>dede</a>
"
false
same structure different names (false)
"<r>
<a/>
<a/>
<b/>
</r>
"
"<r>
<a/>
<b/>
<b/>
</r>
"
false
same text with structure (true)
"<a>y<b/>x</a>
"
"<a>x<b/>y</a>
"
true
attributes vs text (false)
"<a b="c"/>
"
"<a>
<b>c</b>
</a>
"
false