2012-04-25 17 views
6

2つのDOMDocumentオブジェクトを比較したいとします。それらは同じ内容を持っていますが、順序と書式はオフになっている可能性があります。例えば、最初のものは、このXMLを出力します類似のXMLをPHPUnitと比較するには?

<responses> 
    <response id="12"> 
     <foo>bar</foo> 


<lorem>ipsum</lorem> 
      <sit>dolor</sit> 

    </response></responses> 

その他1つの出力:

<responses> 
<response id="12"> 

      <lorem>ipsum</lorem><sit>dolor</sit> 
     <foo>bar</foo> 
          </response> 
</responses> 

あなたが見ることができるように、彼らは同じXML構造が含まれているが、いくつかの要素は、異なる順序や書式にあるかもしれません完全にランダムです。

私が行う場合は、次のコースの

$this->assertEquals(); 

テスト意志は失敗します。私はXML構造だけでなくコンテンツもテストしたくありません。

アイデア?

+0

すべての空白を削除してsha1ハッシュを比較する方法はありますか? –

答えて

3
+1

これは理論的に質問に答えるかもしれませんが、答えの本質的な部分をここに含め、参照用のリンクを提供することが望ましいでしょう(http://meta.stackexchange.com/q/8259)。 – Nanne

+1

確かに、リンクが壊れているので、今日この答えは役に立たない。 – nIcO

+0

@nIcOは壊れたリンクを修正しました –

3

これはどのバージョンのPHPUnitですか?私は最近のバージョンがすべてDomDocumentの比較をサポートしていることは確かです。

ショートバージョン:$doc->preserveWhiteSpace設定を使用して空白を削除し、$doc->C14N()を使用してコメントを削除し、比較できる文字列を取得します。


OKは、ここEOD;行は任意の末尾または先頭の空白を持つことができないことに注意してください、あなたはと遊ぶことができるスクリプトです。

$x1 = <<<EOD 
<responses> 
    <response id="12"> 
     <foo>bar</foo> 

<lorem>ipsum</lorem> 
      <sit>dolor</sit> 
     <!--This is a comment --> 

    </response></responses> 
EOD; 

$x2 = <<<EOD 
<responses> 
<response id="12"> 

      <lorem>ipsum</lorem><sit>dolor</sit> 
     <foo>bar</foo> 
     <!--This is another comment --> 
          </response> 
</responses> 
EOD; 

//次のブロックがStackOverflowの構文強調表示システムが窒息しないように、私はちょうどこのフォーマット-休憩を作ってるんだ、同じファイルの一部です。

$USE_C14N = true; // Try false, just to see the difference. 

$d1 = new DOMDocument(1.0); 
$d2 = new DOMDocument(1.0); 

$d1->preserveWhiteSpace = false; 
$d2->preserveWhiteSpace = false; 

$d1->formatOutput = false; // Only useful for "pretty" output with saveXML() 
$d2->formatOutput = false; // Only useful for "pretty" output with saveXML() 

$d1->loadXML($x1); // Must be done AFTER preserveWhiteSpace and formatOutput are set 
$d2->loadXML($x2); // Must be done AFTER preserveWhiteSpace and formatOutput are set 

if($USE_C14N){ 
    $s1 = $d1->C14N(true, false); 
    $s2 = $d2->C14N(true, false); 
} else { 
    $s1 = $d1->saveXML(); 
    $s2 = $d2->saveXML(); 
} 

echo $s1 . "\n"; 
echo $s2 . "\n"; 

$doc->C14N()が遅くなるかもしれませんが、私はコメントを除去することが望ましいと思わ考えること$USE_C14N=false;

<?xml version="1.0"?> 
<responses><response id="12"><foo>bar</foo><lorem>ipsum</lorem><sit>dolor</sit><!--This is a comment --></response></responses> 

<?xml version="1.0"?> 
<responses><response id="12"><lorem>ipsum</lorem><sit>dolor</sit><foo>bar</foo><!--This is another comment --></response></responses> 

注意と$USE_C14N=true;

<responses><response id="12"><foo>bar</foo><lorem>ipsum</lorem><sit>dolor</sit></response></responses> 
<responses><response id="12"><lorem>ipsum</lorem><sit>dolor</sit><foo>bar</foo></response></responses> 

出力で出力します。これはXMLの空白が重要ではないことを前提としていますが、その前提が正しくないいくつかのユースケースが想定されています...

1

XMLをDOMDocumentsに変更して使用することをお勧めしますassertEqualsこれは既にPHPUnitでサポートされていますが、それはすでにすべてのニーズをカバーしていない可能性があります。

あなたがすることができ、再フォーマットのドキュメントや、同様にそれらを再ロードするPHP XML how to output nice formatを参照してください。

$doc->preserveWhiteSpace = false; 
$doc->formatOutput = true; 

もう一つのアイデアは、彼らのタグ名によって子供その後、並べ替えしないことである - は考えているが、以前に行われている場合。

0

あなたはPHPUnitのassertXmlFileEqualsXmlFile()、assertXmlStringEqualsXmlFile()とassertXmlStringEqualsXmlString()関数を使用することができます。まだ、彼らは唯一のテストは、あなたがPHPのXMLDiff PECL extensionを使用したい、またはあなた自身の再帰的な比較関数を書くかもしれません

Failed asserting that two DOM documents are equal. 

で失敗してみましょう、違うのかについての情報を与えることはありません。時間が問題であれば、単純なAPIのためDOMではなくSimpleXMLを使用することをお勧めします。

0

私はここに紹介されている概念のいくつかを試していて、最終結果を投稿するかもしれないと考えました。私ができるようにしたいことの1つは、2つのノードまたは2つのドキュメントの結果を比較することでした。 (技術的には、類似したドキュメントの最初の子が他と比較されている限り、これと比較することができます)

私はDomDocumentを送信すると、基本的には$ clone-> loadXml - > saveXml)、それが送信されたノードであれば$ clone-> importNode($ obj);を実行します。 DomDocumentもDomNodeのインスタンスであるため、ifの順序が重要になります。

/** 
* @param \DOMDocument|\DOMNode $n1 
* @param \DOMDocument|\DOMNode $n2 
* @return bool 
* @throws \Exception for invalid data 
*/ 
function compareNode($n1, $n2) 
{ 
    $nd1 = new \DOMDocument('1.0', "UTF-8"); 
    if ($n1 instanceof \DOMDocument) { 
     $nd1 = $n1->cloneNode(true); 
     $nd1->preserveWhiteSpace = false; 
     $nd1->formatOutput = false; 
     $nd1->loadXML($n1->saveXML()); 
    } elseif ($n1 instanceof \DOMNode) { 
     $nd1->preserveWhiteSpace = false; 
     $nd1->formatOutput = false; 
     $nd1->importNode($n1); 
    } else { 
     throw new \Exception(__METHOD__ . " node 1 is invalid"); 
    } 

    $nd2 = new \DOMDocument('1.0', "UTF-8"); 
    if ($n2 instanceof \DOMDocument) { 
     $nd2 = $n2->cloneNode(true); 
     $nd2->preserveWhiteSpace = false; 
     $nd2->formatOutput = false; 
     $nd2->loadXML($n2->saveXML()); 
    } elseif ($n1 instanceof \DOMNode) { 
     $nd2->preserveWhiteSpace = false; 
     $nd2->formatOutput = false; 
     $nd2->importNode($n2); 
    } else { 
     throw new \Exception(__METHOD__ . " node 2 is invalid"); 
    } 

    return ($nd1->C14N(true, false) == $nd2->C14N(true, false)); 
} 
関連する問題