2012-05-21 4 views
19

Как мы можем сравнить два элемента HTML, являются ли они идентичными или нет?Как сравнить два элемента HTML

Я попробовал эту вещь, но не повезло

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

А затем на кнопку мыши, я называю проверку()

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

Но это не работает. Все одинаково в двух div. Помимо этого Как мы можем сравнить, являются ли два элемента HTML полностью идентичными или нет. Включая их innerHTML, className, Id и их атрибуты.

Выполнено ли это?

На самом деле, у меня есть два документа HTML, и я хочу удалить идентичный контент из них обоих. Так что два элемента могут иметь одинаковый идентификатор.

PS: Обновление после ценных замечаний Броудера. Если мы сравним два элемента в виде строк, мы не получим соответствия, так как их порядок атрибутов может варьироваться. Единственный вариант - перебирать каждый дочерний атрибут и сопоставлять его. Я все еще должен найти полностью действующую стратегию реализации.

+3

* «Включая их ... Id ...» * Если их значения 'id' совпадают, соответствующий HTML-код недействителен. Значения 'id' ** должны быть уникальными на странице. –

+0

Я предполагаю, что вы хотите обработать два элемента с теми же атрибутами, которые перечислены в другом порядке как эквивалентные ...? Например, '

...
' и '
...
' должно быть совпадением? –

+0

Но тогда они не идентичны * ... –

ответ

26

(см ниже для полного, в основном, непроверенного, и, конечно, не-реорганизованным решения неподготовленного Но первые биты и куски его..)

Сравнивая их 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 

... хотя вы должны спросить себя, является ли эквивалентны эти два элемента в соответствии с вашими критериями:

<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 
    ... 
} 

Обратите внимание, что при сортировке массивов выше, я при условии, что порядок их атрибутов не имеет значения в вашем определении «эквивалент». Надеюсь, так оно и есть, потому что похоже, что оно не сохранилось, поскольку при запуске this test у меня разные результаты из разных браузеров. В этом случае мы должны вернуться к вопросу innerHTML, потому что, если порядок атрибутов на самих элементах не является значительным, то, предположительно, порядок атрибутов для элементов-потомков не должен быть значительным. Если в случае это, вам понадобится рекурсивная функция, которая проверяет потомков в соответствии с вашим определением эквивалента и вообще не использует innerHTML.

Но вы должны уметь собрать что-то вместе с кусками выше, чтобы сравнить два элемента в соответствии с вашими критериями.

Подробнее изучить:


вопрос заинтересовал меня странно, поэтому я пнул вокруг на некоторое время, и придумал следующее. Это, в основном, непроверено, может использовать какой-то рефакторинг и т. Д., Но он должен получить от вас большую часть пути. Я, опять же, предполагаю, что порядок атрибутов не имеет значения. Нижеследующее предполагает, что даже малейшая разница в тексте составляет.

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

Живые примеры:

+2

Спасибо T.J.Cowder..Gonna попробуйте ваше решение и расскажет, как это работает. Спасибо большое btw – sachinjain024

+0

Как насчет сравнения их 'outerHTML'? –

+1

@ Derek: Нет гарантии, что два элемента с одинаковыми атрибутами в другом порядке приведут к тому же самому '' externalHTML''. Это не работает, если вы обертываете и используете 'innerHTML'; см. мой комментарий к другим ответам. –

2

Почему бы не сделать это легкий путь?

<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/

+1

Мне не разрешено редактировать HTML-код. Поэтому я не могу разместить обертку div вокруг элементов. – sachinjain024

+2

Нет гарантии, что элементы с эквивалентными атрибутами в другом порядке будут отсортированы по 'innerHTML'. –

+0

Если вы не можете разместить обертку вокруг, возможно, вы можете использовать код, который я упоминаю + http://stackoverflow.com/questions/2419749/get-selected-elements-outer-html. Таким образом, вам не нужно иметь обертку. – ephemeron

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) ? 
+2

Нет гарантии, что элементы с эквивалентными атрибутами в другом порядке будут отсортированы по 'innerHTML'. –

+1

И, фактически, порядок атрибутов сохраняется, по крайней мере, Chrome: http://jsbin.com/amidip. Так что это просто не работает (если, конечно, порядок атрибутов не является значительным, а другой порядок * должен * привести к не совпадает). –

+1

У этого есть побочный эффект удаления divs из DOM. –

30

Вы можете использовать:

element1.isEqualNode(element2); 

В вашем конкретном примере:

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

The DOM Level 3 Core Spec имеет все детали. По сути, это возвращает истину для двух узлов, имеющих соответствующие атрибуты, потомки и атрибуты потомков.

Существует аналогичный .isSameNode(), который возвращает true, только если оба элемента являются одним и тем же узлом. В вашем примере это не те же узлы, но они равны узлам.

+3

Это лучший ответ. Все остальное просто выполняет сравнение строк или атрибутов. –

+0

Это хороший ответ, только если вам не нужно учитывать атрибуты. из указанных документов: «Следующие строковые атрибуты равны: nodeName, localName, namespaceURI, prefix, nodeValue.». Это означает, что никакие другие атрибуты не проверяются. –

+1

@sJhonny Элемент, который начинается с «Атрибуты NamedNodeMaps равны» означает, что атрибуты тестируются. – Keen