Jak tworzyć obiekty dokumentów za pomocą JavaScript
W Zasadzie to jest pytanie, jak można zbudować Dokument obiekt z ciągu HTML dynamicznie w javascript?
5 answers
Istnieją dwie metody zdefiniowane w specyfikacji, createDocument
od DOM Core Level 2 i createHTMLDocument
z HTML5. Pierwszy tworzy dokument XML (w tym XHTML), drugi tworzy dokument HTML. Oba znajdują się, jako funkcje, na interfejsie DOMImplementation
.
var impl = document.implementation,
xmlDoc = impl.createDocument(namespaceURI, qualifiedNameStr, documentType),
htmlDoc = impl.createHTMLDocument(title);
W rzeczywistości metody te są raczej Młode i zaimplementowane tylko w ostatnich wydaniach przeglądarki. Według http://quirksmode.org i MDN , obsługują następujące przeglądarki createHTMLDocument
:
- Chrome 4
- Opera 10
- Firefox 4
- Internet Explorer 9
- Safari 4
Co ciekawe, można (jakby) utworzyć dokument HTML w starszych wersjach Internet Explorera, używając ActiveXObject
:
var htmlDoc = new ActiveXObject("htmlfile");
Wynikowy obiekt będzie nowym dokumentem, którym można manipulować tak jak każdym innym dokumentem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-22 17:54:18
Zakładając, że próbujesz utworzyć w pełni przetworzony obiekt dokumentu z ciągu znaczników i typu zawartości, który również znasz – może dlatego, że uzyskałeś html z XMLHttpRequest, a tym samym uzyskałeś content-type w nagłówku http Content-Type
; prawdopodobnie Zwykle text/html
) - powinno to być takie proste:
var doc = (new DOMParser).parseFromString(markup, mime_type);
W idealnym świecie przyszłości, gdzie implementacje przeglądarki DOMParser
są tak silne i kompetentne, jak ich renderowanie dokumentów – być może jest to dobry wymóg marzeń o przyszłości HTML6
wysiłki norm. Okazuje się jednak, że nie ma obecnych przeglądarek.
Prawdopodobnie masz łatwiejszy (ale nadal bałagan) problem z ciągiem html, dla którego chcesz uzyskać w pełni przetworzony obiekt Document
. Oto jeszcze jedno podejście do tego, jak to zrobić, które również powinno działać we wszystkich przeglądarkach – najpierw tworzysz obiekt HTML Document
:
var doc = document.implementation.createHTMLDocument('');
A następnie uzupełnij go fragmentem html :
doc.open();
doc.write(html);
doc.close();
Teraz powinieneś mieć w pełni parsowany DOM w doc, który możesz uruchomić alert(doc.title)
on, wycinanie za pomocą selektorów css, takich jak doc.querySelectorAll('p')
lub ditto XPath za pomocą doc.evaluate
.
To działa w nowoczesnych przeglądarkach WebKit, takich jak Chrome i Safari – właśnie testowałem w Chrome 22 i Safari 6 odpowiednio) - oto przykład, który pobiera kod źródłowy bieżącej strony, odtwarza go w nowej zmiennej dokumentu src
, odczytuje jego tytuł, nadpisuje go za pomocą cytowanej wersji html tego samego kodu źródłowego i pokazuje wynik w iframe: http://codepen.io/johan/full/KLIeE
Niestety, nie sądzę, aby inne współczesne przeglądarki miały jeszcze tak solidne implementacje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-04 22:01:13
Zgodnie z spec ( doc ), można użyć createHTMLDocument
Metody DOMImplementation
, dostępnej za pośrednictwem document.implementation
w następujący sposób:
var doc = document.implementation.createHTMLDocument('My title');
var body = document.createElementNS('http://www.w3.org/1999/xhtml', 'body');
doc.documentElement.appendChild(body);
// and so on
- jsFiddle: http://jsfiddle.net/9Fh7R /
- dokument MDN dla
DOMImplementation
: https://developer.mozilla.org/en/DOM/document.implementation - dokument MDN dla
DOMImplementation.createHTMLDocument
: https://developer.mozilla.org/En/DOM/DOMImplementation.createHTMLDocument
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-22 18:00:52
Zaktualizowana odpowiedź na 2014 rok, w miarę rozwoju Domparsera. Działa to we wszystkich obecnych przeglądarkach, które mogę znaleźć, i powinno działać również we wcześniejszych wersjach IE, używając dokumentu ecManaut.wdrożenie.createHTMLDocument ( " ) podejście powyżej.
Zasadniczo, IE, Opera, Firefox mogą Wszystkie parsować jako "tekst / html". Safari przetwarza jako "tekst / xml".
Uważaj jednak na nietolerancyjne parsowanie XML. Analizator Safari ulegnie rozbiciu na niełamliwe spacje i inne znaki HTML (francuski / niemiecki akcenty) oznaczane ampersandami. Zamiast obsługiwać każdy znak oddzielnie, poniższy kod zastępuje wszystkie ampersands bezsensownym ciągiem znaków " j!J!". Ten łańcuch może być następnie ponownie renderowany jako ampersand podczas wyświetlania wyników w przeglądarce (prostsze, jak znalazłem, niż próba obsługi Ampersand w" fałszywym " parsowaniu XML).
function parseHTML(sText) {
try {
console.log("Domparser: " + typeof window.DOMParser);
if (typeof window.DOMParser !=null) {
// modern IE, Firefox, Opera parse text/html
var parser = new DOMParser();
var doc = parser.parseFromString(sText, "text/html");
if (doc != null) {
console.log("parsed as HTML");
return doc
}
else {
//replace ampersands with harmless character string to avoid XML parsing issues
sText = sText.replace(/&/gi, "j!J!");
//safari parses as text/xml
var doc = parser.parseFromString(sText, "text/xml");
console.log("parsed as XML");
return doc;
}
}
else {
// older IE
doc= document.implementation.createHTMLDocument('');
doc.write(sText);
doc.close;
return doc;
}
} catch (err) {
alert("Error parsing html:\n" + err.message);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-27 23:56:27
Poniższe działa w większości popularnych przeglądarek, ale nie w niektórych. To jest jak proste powinno BYĆ (ale nie jest):
// Fails if UA doesn't support parseFromString for text/html (e.g. IE)
function htmlToDoc(markup) {
var parser = new DOMParser();
return parser.parseFromString(markup, "text/html");
}
var htmlString = "<title>foo bar</title><div>a div</div>";
alert(htmlToDoc(htmlString).title);
Aby uwzględnić kaprysy agenta użytkownika, może być lepiej (zwróć uwagę na atrybucję):
/*
* DOMParser HTML extension
* 2012-02-02
*
* By Eli Grey, http://eligrey.com
* Public domain.
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*
* Modified to work with IE 9 by RobG
* 2012-08-29
*
* Notes:
*
* 1. Supplied markup should be avalid HTML document with or without HTML tags and
* no DOCTYPE (DOCTYPE support can be added, I just didn't do it)
*
* 2. Host method used where host supports text/html
*/
/*! @source https://gist.github.com/1129031 */
/*! @source https://developer.mozilla.org/en-US/docs/DOM/DOMParser */
/*global document, DOMParser*/
(function(DOMParser) {
"use strict";
var DOMParser_proto;
var real_parseFromString;
var textHTML; // Flag for text/html support
var textXML; // Flag for text/xml support
var htmlElInnerHTML; // Flag for support for setting html element's innerHTML
// Stop here if DOMParser not defined
if (!DOMParser) return;
// Firefox, Opera and IE throw errors on unsupported types
try {
// WebKit returns null on unsupported types
textHTML = !!(new DOMParser).parseFromString('', 'text/html');
} catch (er) {
textHTML = false;
}
// If text/html supported, don't need to do anything.
if (textHTML) return;
// Next try setting innerHTML of a created document
// IE 9 and lower will throw an error (can't set innerHTML of its HTML element)
try {
var doc = document.implementation.createHTMLDocument('');
doc.documentElement.innerHTML = '<title></title><div></div>';
htmlElInnerHTML = true;
} catch (er) {
htmlElInnerHTML = false;
}
// If if that failed, try text/xml
if (!htmlElInnerHTML) {
try {
textXML = !!(new DOMParser).parseFromString('', 'text/xml');
} catch (er) {
textHTML = false;
}
}
// Mess with DOMParser.prototype (less than optimal...) if one of the above worked
// Assume can write to the prototype, if not, make this a stand alone function
if (DOMParser.prototype && (htmlElInnerHTML || textXML)) {
DOMParser_proto = DOMParser.prototype;
real_parseFromString = DOMParser_proto.parseFromString;
DOMParser_proto.parseFromString = function (markup, type) {
// Only do this if type is text/html
if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
var doc, doc_el, first_el;
// Use innerHTML if supported
if (htmlElInnerHTML) {
doc = document.implementation.createHTMLDocument("");
doc_el = doc.documentElement;
doc_el.innerHTML = markup;
first_el = doc_el.firstElementChild;
// Otherwise use XML method
} else if (textXML) {
// Make sure markup is wrapped in HTML tags
// Should probably allow for a DOCTYPE
if (!(/^<html.*html>$/i.test(markup))) {
markup = '<html>' + markup + '<\/html>';
}
doc = (new DOMParser).parseFromString(markup, 'text/xml');
doc_el = doc.documentElement;
first_el = doc_el.firstElementChild;
}
// RG: I don't understand the point of this, I'll leave it here though
// In IE, doc_el is the HTML element and first_el is the HEAD.
//
// Is this an entire document or a fragment?
if (doc_el.childElementCount == 1 && first_el.localName.toLowerCase() == 'html') {
doc.replaceChild(first_el, doc_el);
}
return doc;
// If not text/html, send as-is to host method
} else {
return real_parseFromString.apply(this, arguments);
}
};
}
}(DOMParser));
// Now some test code
var htmlString = '<html><head><title>foo bar</title></head><body><div>a div</div></body></html>';
var dp = new DOMParser();
var doc = dp.parseFromString(htmlString, 'text/html');
// Treat as an XML document and only use DOM Core methods
alert(doc.documentElement.getElementsByTagName('title')[0].childNodes[0].data);
Nie zniechęcaj się ilością kodu, jest dużo komentarzy, można go nieco skrócić, ale staje się mniej czytelny.
Oh, a jeśli znacznik jest poprawny XML, życie jest znacznie prostsze:
var stringToXMLDoc = (function(global) {
// W3C DOMParser support
if (global.DOMParser) {
return function (text) {
var parser = new global.DOMParser();
return parser.parseFromString(text,"application/xml");
}
// MS ActiveXObject support
} else {
return function (text) {
var xmlDoc;
// Can't assume support and can't test, so try..catch
try {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(text);
} catch (e){}
return xmlDoc;
}
}
}(this));
var doc = stringToXMLDoc('<books><book title="foo"/><book title="bar"/><book title="baz"/></books>');
alert(
doc.getElementsByTagName('book')[2].getAttribute('title')
);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-29 07:27:32