Отримайте рядкове представлення вузла DOM


96

Javascript: у мене є DOM-представлення вузла (елемента чи документа), і я шукаю рядкове його представлення. Наприклад,

var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));

повинен дати:

get_string(el) == "<p>Test</p>";

У мене є сильне відчуття, що мені не вистачає чогось тривіально простого, але я просто не знаходжу методу, який працює в IE, FF, Safari та Opera. Тому зовнішній HTML не є варіантом.


4
Імовірно, версія 11 Firefox також підтримує зовнішнійHTML: bugzilla.mozilla.org/show_bug.cgi?id=92264
Boldewyn

1
Наразі виглядає IE, FF, Safari, Chrome, Opera, всі підтримують зовнішнійHTML, див. Developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
wangf

1
Так, це тепер (з 2009 року, тобто) стало тривіальним завданням :)
Boldewyn

Так, безумовно,
зовнішнійHTML

Відповіді:


133

Ви можете створити тимчасовий батьківський вузол і отримати внутрішній вміст HTML:

var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));

var tmp = document.createElement("div");
tmp.appendChild(el);
console.log(tmp.innerHTML); // <p>Test</p>

EDIT: Будь ласка, дивіться відповідь нижче про externalHTML. el.outerHTML повинен бути всім необхідним.


1
Ой. Настільки просте ... Лише невелика примітка: Якщо я хочу, щоб весь документ був "закреслений", я можу використовувати той самий метод з document.documentElement (casecase: AJAX запити). Можливо, ви могли б включити це у відповідь?
Болдевін,

3
@Boldewyn: ви можете додати ціле document.documentElementу div? Святе дерьмо ....
Roatin Marth

Простий, як чорт ... +1 Дуже поганий документFragment не підтримує внутрішнійHTML
Lajos Meszaros

30
externalHTML - відповідь
neaumusic

3
Не забудьте клонувати свій файл elementперед тим, як додати його до себе, tmpколи ви додасте його tmp, його буде видалено з document.
Olcay Ertaş,

44

Те, що ви шукаєте, це "externalHTML", але вам потрібен резервний варіант, оскільки він не сумісний зі старими браузерами.

var getString = (function() {
  var DIV = document.createElement("div");

  if ('outerHTML' in DIV)
    return function(node) {
      return node.outerHTML;
    };

  return function(node) {
    var div = DIV.cloneNode();
    div.appendChild(node.cloneNode(true));
    return div.innerHTML;
  };

})();

// getString(el) == "<p>Test</p>"

Тут ви знайдете мій плагін jQuery: Отримайте зовнішній HTML вибраного елемента


Firefox додано outerHTMLу версії 11 після того, як я задав питання. Тоді це тоді не було варіантом. Я навіть оновив своє запитання відповідним коментарем, якщо уважно придивитися.
Boldewyn

Це правильно, бо ви скидаєте ідентифікатори елементів та інші атрибути, якщо використовуєтеinnerHtml
Сергій Панфілов

1
@SergeyPanfilov: я нічого не кидав, тому що загорнув вузол у порожній дів перед тим, як дзвонити innerHTML; )
gtournie

3
У 2015 році я б сказав, що це далеко не найкраща відповідь.
ACK_stoverflow

Так, на сьогоднішній день лише дуже старі (IE> 10, Safari> 7, справді старовинний FF, Chrome) та / або неясні браузери (Opera Mini) не підтримують outerHTMLатрибут. Див. Також caniuse.com/#feat=xml-serializer
Герт Сондербі

20

Я не думаю, що для цього вам потрібен якийсь складний сценарій. Просто використовуйте

get_string=(el)=>el.outerHTML;

це найкраща відповідь
Аврахам

15

Під FF ви можете використовувати XMLSerializerоб'єкт для серіалізації XML у рядок. IE надає вам xmlвластивість вузла. Отже, ви можете зробити наступне:

function xml2string(node) {
   if (typeof(XMLSerializer) !== 'undefined') {
      var serializer = new XMLSerializer();
      return serializer.serializeToString(node);
   } else if (node.xml) {
      return node.xml;
   }
}

FYI .xmlне працює на DOM-вузлах (як у вузлах на поточній сторінці). Він працює лише на вузлах документів XML DOM.
Півмісяць свіжий

І навпаки, outerHTMLне працює на вузлах документів XML DOM. Він працює лише на DOM-вузлах (як у вузлах на поточній сторінці). Хороша послідовність, я б сказав.
Crescent Fresh

7

Використовуйте елемент # externalHTML:

var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));

console.log(el.outerHTML);

Він також може бути використаний для запису елементів DOM. З документації Mozilla:

Зовнішній атрибутHTML інтерфейсу елемента DOM отримує серіалізований фрагмент HTML, що описує елемент, включаючи його нащадків. Його можна встановити для заміни елемента вузлами, проаналізованими з заданого рядка.

https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML


3

Використовуйте element.outerHTML, щоб отримати повне представлення елемента, включаючи зовнішні теги та атрибути.


1

Якщо ваш елемент має батька

element.parentElement.innerHTML

2
Дякую за відповідь! На жаль, це вже було запропоновано, але відповідач видалив відповідь. Проблема полягає в тому, що батько може містити набагато більше розмітки, ніж хотілося. Подумайте про зовнішній HTML для окремої частини <li>у списку.
Болдевін

1

Спробуйте

new XMLSerializer().serializeToString(element);

Дякую за пропозицію, але саме це запропонував Брайан Кейл у своїй відповіді.
Болдевін,

1

Я виявив, що для моїх випадків використання я не завжди хочу весь зовнішній HTML. Багато вузлів просто мають занадто багато дітей, щоб показати.

Ось функція (мінімально перевірена в Chrome):

/**
 * Stringifies a DOM node.
 * @param {Object} el - A DOM node.
 * @param {Number} truncate - How much to truncate innerHTML of element.
 * @returns {String} - A stringified node with attributes
 *                     retained.
 */
function stringifyEl(el, truncate) {
    var truncateLen = truncate || 50;
    var outerHTML = el.outerHTML;
    var ret = outerHTML;
    ret = ret.substring(0, truncateLen);

    // If we've truncated, add an elipsis.
    if (outerHTML.length > truncateLen) {
      ret += "...";
    }
    return ret;
}

https://gist.github.com/kahunacohen/467f5cc259b5d4a85eb201518dcb15ec


0

Я витратив багато часу на з'ясування того, що не так, коли я переглядаю DOMElements з кодом у прийнятій відповіді. Це те, що мені вдалося, інакше кожен другий елемент зникає з документа:

_getGpxString: function(node) {
          clone = node.cloneNode(true);
          var tmp = document.createElement("div");
          tmp.appendChild(clone);
          return tmp.innerHTML;
        },

1
Я не вважаю, що у вас тут інша проблема. Зауважте, що наведене вище рішення видаляє вихідний елемент із DOM. Отже, коли ви використовуєте живу колекцію на кшталт document.getElementsByTagName(), ця колекція зміниться в середній forчастині, отже, пропуск кожного другого елемента.
Болдевін,

-1

якщо використовується реакція:

const html = ReactDOM.findDOMNode(document.getElementsByTagName('html')[0]).outerHTML;

.outerHTMLне є специфічним для Реакції; це стандарт DOM. Перевірте відповідь @Rich Apodaca.
chharvey

так ... цікавиною (якщо використовую реакцію) моєї відповіді було reactdom.findDOMNode()..., не те .outerHTML, а спасибі за позицію.
victorkurauchi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.