6

それで、2つのDOMDocumentオブジェクトを比較したいとしましょう。それらは同じ内容ですが、順序とフォーマットがずれている可能性があります。たとえば、最初のXMLは次のXMLを出力します。

<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構造だけでなく、コンテンツもテストしたくありません。

何か案は?

4

6 に答える 6

4

これで問題は解決したようです。

https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertXmlStringEqualsXmlString

于 2012-04-26T09:26:30.153 に答える
3

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

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


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

    $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";

で出力$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>

で出力$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>

$doc->C14N()遅くなるかもしれませんが、コメントを取り除くことが望ましいと思われることに注意してください。これはすべて、XMLの空白が重要ではないことも前提としていることに注意してください。おそらく、その前提が正しくないユースケースがいくつかあります...

于 2012-04-25T16:53:25.580 に答える
1

XMLを変換して、それらでDOMDocuments使用することをお勧めしますassertEquals。それはすでにPHPUnitによってサポートされています-しかし、それはあなたのすべてのニーズをまだカバーしていないかもしれません。

ドキュメントを再フォーマットして再ロードすることもできます。PHPXMLで適切なフォーマットを出力する方法を参照してください。

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

もう1つのアイデアは、タグ名で子を並べ替えることです。これが以前に行われたことがあるかどうかはわかりません。

于 2012-04-25T16:53:41.043 に答える
0

PHPUnitのassertXmlFileEqualsXmlFile()、assertXmlStringEqualsXmlFile()およびassertXmlStringEqualsXmlString()関数を使用できます。それでも、彼らは何が違うのかについての情報を提供しません、彼らはテストを失敗させるだけです

Failed asserting that two DOM documents are equal.

したがって、PHPのXMLDiff PECL拡張機能を使用するか、独自の再帰比較関数を作成することをお勧めします。時間が重要な場合は、APIが単純なため、DOMではなくSimpleXMLを使用することをお勧めします。

于 2014-02-07T09:02:20.700 に答える
0

私はここに提示された概念のいくつかで遊んでいて、最終結果を投稿したほうがよいと考えました。私がやりたかったことの1つは、2つのノードまたは2つのドキュメントの結果を比較することでした。(技術的には、これは、類似したドキュメントの最初の子が別の子と比較されている限り、どちらかを比較できます)

基本的に、DomDocumentを送信すると、$ clone-> loadXml($ obj-> 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));
}
于 2015-11-24T21:46:10.067 に答える
0

次のアサーションを使用します。

$this->assertXmlStringEqualsXmlString($expected, $actual);
于 2019-05-29T07:23:33.883 に答える