Uzyskaj ciąg reprezentujący węzeł DOM


97

JavaScript: Mam reprezentację DOM węzła (elementu lub dokumentu) i szukam reprezentacji ciągu. Na przykład,

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

powinno dać:

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

Mam silne przeczucie, że brakuje mi czegoś trywialnie prostego, ale po prostu nie znajduję metody, która działa w IE, FF, Safari i Opera. Dlatego zewnętrznyHTML nie jest opcją.


4
Prawdopodobnie w wersji 11 Firefox obsługuje również zewnętrzną wersję HTML: bugzilla.mozilla.org/show_bug.cgi?id=92264
Boldewyn,

1
Na razie wygląda IE, FF, Safari, Chrome, Opera wszystkie obsługują zewnętrzną HTML, patrz developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
wangf

1
Tak, teraz (czyli od 2009 roku) stało się to trywialnym zadaniem :)
Boldewyn 22.04.15

Tak, zdecydowanie externalHTML
neaumusic

Odpowiedzi:


134

Możesz utworzyć tymczasowy węzeł nadrzędny i pobrać jego zawartość innerHTML:

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>

EDYCJA: Zobacz odpowiedź poniżej na temat externalHTML. el.outerHTML powinien być wszystkim, czego potrzeba.


1
Auć. To takie proste ... Tylko mała uwaga: jeśli chcę, aby cały dokument został poddany „stringifikacji”, mogę użyć tej samej metody z document.documentElement (przypadek użycia: żądania AJAX). Może mógłbyś uwzględnić to w odpowiedzi?
Boldewyn

3
@Boldewyn: możesz dołączyć całość document.documentElementdo elementu DIV?
Cholera

Proste, jak cholera ... +1 Szkoda documentFragment nie obsługuje innerHTML
Lajos Meszaros

30
Odpowiedź brzmi:
externalHTML

3
Nie zapomnij sklonować swojego elementprzed dodaniem, tmpponieważ kiedy dodasz go do tmp, zostanie usunięty z document.
Olcay Ertaş

45

To, czego szukasz, to „externalHTML”, ale potrzebujemy rozwiązania zastępczego, ponieważ nie jest ono zgodne ze starymi przeglądarkami.

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

Znajdziesz moją wtyczkę jQuery tutaj: Pobierz zewnętrzny kod HTML wybranego elementu


Firefox został dodany outerHTMLw wersji 11, po tym, jak zadałem pytanie. Więc to nie było wtedy możliwe. Zaktualizowałem nawet moje pytanie odpowiednim komentarzem, jeśli przyjrzysz się uważnie.
Boldewyn

Zgadza się, bo upuszczasz identyfikatory elementów i inne atrybuty, jeśli używaszinnerHtml
Sergei Panfilov

1
@SergeyPanfilov: Niczego nie upuściłem, ponieważ przed wywołaniem zawiniłem węzeł w pusty element div innerHTML; )
gtournie

3
W 2015 roku powiedziałbym, że to zdecydowanie najlepsza odpowiedź.
ACK_stoverflow

Tak, na dzień dzisiejszy tylko bardzo stare (IE> 10, Safari> 7, prawdziwie starożytne FF, Chrome) i / lub mało znane przeglądarki (Opera Mini) nie obsługują tego outerHTMLatrybutu. Zobacz także caniuse.com/#feat=xml-serializer
Gert Sønderby

20

Myślę, że nie potrzebujesz do tego żadnego skomplikowanego skryptu. Po prostu użyj

get_string=(el)=>el.outerHTML;

to najlepsza odpowiedź
Avraham

15

W FF możesz użyć XMLSerializerobiektu do serializacji XML do łańcucha. IE udostępnia xmlwłaściwość węzła. Możesz więc wykonać następujące czynności:

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

FYI .xmlnie działa na węzłach DOM (tak jak w węzłach na bieżącej stronie). Działa tylko na węzłach dokumentów XML DOM.
Crescent Fresh

I odwrotnie, outerHTMLnie działa na węzłach dokumentów XML DOM. Działa tylko na węzłach DOM (jak w węzłach na bieżącej stronie). Powiedziałbym, że dobra konsystencja.
Crescent Fresh

7

Użyj elementu # externalHTML:

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

console.log(el.outerHTML);

Może być również używany do pisania elementów DOM. Z dokumentacji Mozilli:

Atrybut externalHTML elementu interfejsu DOM pobiera zserializowany fragment HTML opisujący element, w tym jego potomków. Można ustawić, aby zastąpić element węzłami przeanalizowanymi z podanego ciągu.

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


3

Użyj element.outerHTML, aby uzyskać pełną reprezentację elementu, w tym zewnętrzne znaczniki i atrybuty.


1

Jeśli twój element ma rodzica

element.parentElement.innerHTML

2
Dziękuję za odpowiedź! Niestety było to już zasugerowane, ale osoba odpowiadająca usunęła odpowiedź. Problem polega na tym, że rodzic może zawierać dużo więcej znaczników niż chciał. Pomyśl o zewnętrznymHTML dla pojedynczego <li>elementu na liście.
Boldewyn

1

Próbować

new XMLSerializer().serializeToString(element);

Dziękuję za sugestię, ale dokładnie to zasugerował Bryan Kale w swojej odpowiedzi.
Boldewyn

1

Odkryłem, że dla moich przypadków użycia nie zawsze chcę mieć cały zewnętrzny HTML. Wiele węzłów ma po prostu zbyt wiele dzieci do pokazania.

Oto funkcja (minimalnie przetestowana w 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

Zmarnowałem dużo czasu, zastanawiając się, co jest nie tak, gdy przechodzę przez DOMElements z kodem w zaakceptowanej odpowiedzi. U mnie to zadziałało, inaczej co drugi element znika z dokumentu:

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

1
Nie wychodzę z kończyny, kiedy przypuszczam, że masz tu inny problem. Zwróć uwagę, że powyższe rozwiązanie usuwa oryginalny element z DOM. Tak więc, kiedy używasz kolekcji na żywodocument.getElementsByTagName() , takiej jak , ta kolekcja zmieni się w połowie forpętli, stąd pomijanie co drugiego elementu.
Boldewyn

-1

jeśli używasz Reaguj:

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

.outerHTMLnie jest specyficzne dla Reacta; jest to standard DOM. Sprawdź odpowiedź @Rich Apodaca.
chharvey

tak ... interesującym punktem (jeśli korzystam z Reaguj) na mojej odpowiedzi było reactdom.findDOMNode()... nie .outerHTML, ale dzięki za stanowisko.
Victorkurauchi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.