31

2つのHTML要素が同一であるかどうかを比較するにはどうすればよいですか?

私はこれを試しましたが、運がありません

<div class="a"> Hi this is sachin tendulkar </div>
<div class="a"> Hi this is sachin tendulkar </div>

次に、ボタンをクリックすると、関数check()を呼び出します。

var divs = $(".a");
alert(divs.length);    // Shows 2 here which is correct
if (divs.get(0) == divs.get(1)) alert("Same");

しかし、これは機能していません。2つのdivですべてが同じです。これとは別に、2つのHTML要素が完全に同一であるかどうかをどのように比較できますか。それらのinnerHTML、className、Id、およびそれらの属性を含みます。

これは実行可能ですか?

実際、私は2つのHTMLドキュメントを持っていて、両方から同じコンテンツを削除したいので、2つの要素が同じIDを持つことができます。

PS:クロウダーの貴重なコメントの後に更新します。2つの要素を文字列として比較する場合、属性の順序が異なる可能性があるため、一致は得られません。したがって、唯一のオプションは、各子属性を反復処理して一致させることです。私はまだ完全に機能する実装戦略を理解する必要があります。

4

4 に答える 4

55

次を使用できます。

element1.isEqualNode(element2);

あなたの特定の例では:

var divs = $(".a");
if ( divs.get(0).isEqualNode(divs.get(1)) ) alert("Same");

DOMレベル3コアスペックにはすべての詳細があります。基本的に、これは、一致する属性、子孫、および子孫の属性を持つ2つのノードに当てはまります。

両方の要素が同じノードである場合にのみtrueを返す同様の.isSameNode()があります。あなたの例では、これらは同じノードではありませんが、等しいノードです。

于 2013-10-13T06:37:24.263 に答える
33

アップデート

キーンの回答、密接に関連する質問に対するccprojの回答を参照してください。これにはありますが、テキストとして属性をisEqualNode比較するため、同じクラスのセットまたは同じスタイルプロパティのセットを異なる順序で使用すると、ノードは同等ではないと見なされます。ccprogの答えはそれを処理します。classstyle

元の回答

(完全で、ほとんどテストされておらず、確かにリファクタリングされていないオフザカフソリューションについては、以下を参照してください。しかし、最初に、その断片。)

それらの比較innerHTMLは簡単です。

if (divs[0].innerHTML === divs[1].innerHTML)
// or if you prefer using jQuery
if (divs.html() === $(divs[1]).html()) // The first one will just be the HTML from div 0

...ただし、これら2つの要素が基準に従って同等であるかどうかを自問する必要があります。

<div><span class="foo" data-x="bar">x</span></div>
<div><span data-x="bar" class="foo">x</span></div>

...それらinnerHTML異なるため(少なくともChromeでは、すべてではないにしてもほとんどのブラウザで疑わしい)。(詳細は以下をご覧ください。)

次に、それらのすべての属性を比較する必要があります。私の知る限り、jQueryは属性を列挙する手段を提供しませんが、DOMは次のことを提供します。

function getAttributeNames(node) {
  var index, rv, attrs;

  rv = [];
  attrs = node.attributes;
  for (index = 0; index < attrs.length; ++index) {
    rv.push(attrs[index].nodeName);
  }
  rv.sort();
  return rv;
}

それで

var names = [getAttributeNames(div[0]), getAttributeNames(div[1])];
if (names[0].length === names[1].length) {
    // Same number, loop through and compare names and values
    ...
}

上記の配列を並べ替えることにより、「同等」の定義では属性の順序は重要ではないと想定していることに注意してください。このテストを実行すると、ブラウザごとに異なる結果が得られるため、保存されていないように見えるため、そうなることを願っています。innerHTMLその場合、要素自体の属性の順序が重要でない場合は、おそらく子孫要素の属性の順序が重要ではないため、質問に戻る必要があります。その場合は、同等の定義に従って子孫をチェックし、まったく使用innerHTMLしない再帰関数が必要になります。

次に、この後続の質問によって提起された懸念があります。要素が異なるが同等のstyle属性を持っている場合はどうなりますか?例えば:

<div id="a" style="color: red; font-size: 28px">TEST A</div>
<div id="b" style="font-size: 28px; color: red">TEST B</div>

そこでの私の答えstyleは、次のように要素のオブジェクトのコンテンツをループすることによってそれに対処します。

const astyle = div[0].style;
const bstyle = div[1].style;
const rexDigitsOnly = /^\d+$/;
for (const key of Object.keys(astyle)) {
    if (!rexDigitsOnly.test(key) && astyle[key] !== bstyle[key]) {
        // Not equivalent, stop
    }
}
// Equivalent

悲しいことに、私がその答えで言うように:

少なくとも一部のブラウザでは、(一方が持っていcolor: redてもう一方が持っているcolor: #ff0000場合、上記は失敗することに注意してください。スタイルプロパティが文字列値を使用する場合、通常、正規化ではなく、指定された方法で値を取得するためです。getComputedStyle代わりに計算された(ish)値を取得するために使用できますが、CSSの適用性に関する問題が発生します。まったくgetComputedStyle同じマークアップを持つ2つの要素は、DOM内の場所と、それらに適用されるCSSのために、異なる値を持つ可能性があります。結果。またgetComputedStyle、ドキュメントに含まれていないノードでは機能しないため、ノードのクローンを作成してその問題を除外することはできません。

しかし、あなたはあなたの基準に従って2つの要素を比較するために上記の部分から何かをまとめることができるはずです。

さらに探索する:


不思議なことにその質問に興味があったので、しばらくそれを見て回って、次のことを思いついた。ほとんどテストされておらず、リファクタリングなどを使用できますが、ほとんどの場合、そこに到達するはずです。繰り返しになりますが、属性の順序は重要ではないと思います。以下は、テキストのわずかな違いでも重要であると想定しています。

function getAttributeNames(node) {
  var index, rv, attrs;

  rv = [];
  attrs = node.attributes;
  for (index = 0; index < attrs.length; ++index) {
    rv.push(attrs[index].nodeName);
  }
  rv.sort();
  return rv;
}

function equivElms(elm1, elm2) {
  var attrs1, attrs2, name, node1, node2;

  // Compare attributes without order sensitivity
  attrs1 = getAttributeNames(elm1);
  attrs2 = getAttributeNames(elm2);
  if (attrs1.join(",") !== attrs2.join(",")) {
    display("Found nodes with different sets of attributes; not equiv");
    return false;
  }

  // ...and values
  // unless you want to compare DOM0 event handlers
  // (onclick="...")
  for (index = 0; index < attrs1.length; ++index) {
    name = attrs1[index];
    if (elm1.getAttribute(name) !== elm2.getAttribute(name)) {
      display("Found nodes with mis-matched values for attribute '" + name + "'; not equiv");
      return false;
    }
  }

  // Walk the children
  for (node1 = elm1.firstChild, node2 = elm2.firstChild;
       node1 && node2;
       node1 = node1.nextSibling, node2 = node2.nextSibling) {
     if (node1.nodeType !== node2.nodeType) {
       display("Found nodes of different types; not equiv");
       return false;
     }
     if (node1.nodeType === 1) { // Element
       if (!equivElms(node1, node2)) {
         return false;
       }
     }
     else if (node1.nodeValue !== node2.nodeValue) {
       display("Found nodes with mis-matched nodeValues; not equiv");
       return false;
     }
  }
  if (node1 || node2) {
    // One of the elements had more nodes than the other
    display("Found more children of one element than the other; not equivalent");
    return false;
  }

  // Seem the same
  return true;
}

実例:

于 2012-05-21T05:16:30.833 に答える
1

簡単な方法でやってみませんか?

<div id="div1"><div class="a"> Hi this is sachin tendulkar </div></div>
<div id="div2"><div class="a"> Hi this is sachin tendulkar </div></div>

if($('#div1').html() == $('#div2').html())
    alert('div1 & div2 are the same');        
else
    alert('div1 & div2 are different');

http://jsfiddle.net/5Zwy8/1/

于 2012-05-21T05:21:14.677 に答える
0

このコードはどのようになっていますか?

var d1 = document.createElement("div");
d1.appendChild(divs.get(0));
var d2 = document.createElement("div");
d2.appendChild(divs.get(1));
if (d1.innerHTML == d2.innerHTML) ?
于 2012-05-21T05:22:06.890 に答える