Получить строковое представление узла 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.