Получить строковое представление узла DOM


97

Javascript: у меня есть представление DOM узла (элемента или документа), и я ищу его строковое представление. Например,

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

должен дать:

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

У меня есть сильное чувство, что мне не хватает чего-то банально простого, но я просто не нашел метода, который работал бы в IE, FF, Safari и Opera. Следовательно, externalHTML - не вариант.


4
Предположительно, версия 11 Firefox также поддерживает externalHTML: bugzilla.mozilla.org/show_bug.cgi?id=92264
— Boldewyn

1
На данный момент, выглядит IE, FF, Safari, Chrome, Opera все поддерживают outerHTML, см developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
— wangf

1
Да, это теперь (то есть с 2009 года) стало тривиальной задачей :)
— Болдевин

Да, определенно externalHTML
— neaumusic

Ответы:


134

Вы можете создать временный родительский узел и получить его внутреннее 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>

РЕДАКТИРОВАТЬ: см. Ответ ниже о externalHTML. el.outerHTML должен быть всем, что нужно.


1
Ой. Так просто ... Небольшое примечание: если я хочу, чтобы весь документ был "структурирован", я могу использовать тот же метод с document.documentElement (вариант использования: запросы AJAX). Возможно, вы могли бы включить это в ответ?
— Boldewyn

3
@Boldewyn: вы можете добавить все document.documentElementв div?
— Черт побери

Просто, черт возьми ... +1 Жаль, что documentFragment не поддерживает innerHTML
— Лайош Месарош

30
externalHTML - это ответ
— neaumusic

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

45

То, что вы ищете, это '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: Я ничего не уронил, потому что перед вызовом я обернул узел в пустой div innerHTML; )
— gtournie

3
В 2015 году я бы сказал, что это, безусловно, лучший ответ.
— ACK_stoverflow

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


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.
— Crescent Fresh

И наоборот, outerHTMLне работает с узлами документа XML DOM. Он работает только с узлами DOM (как с узлами на текущей странице). Я бы сказал, хорошая последовательность.
— Crescent Fresh

7

Используйте Element # outerHTML:

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

console.log(el.outerHTML);

Его также можно использовать для написания элементов DOM. Из документации Mozilla:

Атрибут outerHTML интерфейса DOM элемента получает сериализованный фрагмент HTML, описывающий элемент, включая его потомков. Его можно настроить для замены элемента узлами, извлеченными из данной строки.

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


3

Используйте element.outerHTML, чтобы получить полное представление элемента, включая внешние теги и атрибуты.


1

Если у вашего элемента есть родитель

element.parentElement.innerHTML

2
Спасибо за ответ! К сожалению, это уже было предложено, но ответчик удалил ответ. Проблема в том, что родительский объект может содержать намного больше разметки, чем хотелось бы. Подумайте о externalHTML для одного<li> в списке.
— Boldewyn 02

1

Пытаться

new XMLSerializer().serializeToString(element);

Спасибо за предложение, но это именно то, что Брайан Кейл предложил в своем ответе.
— Boldewyn 06

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цикла, следовательно, каждый второй элемент пропускается.
— Boldewyn

-1

при использовании реакции:

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

.outerHTMLне зависит от React; это стандарт DOM. Посмотрите ответ @Rich Apodaca.
— chharvey

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