Parse a HTML string with JS

Szukałem rozwiązania, ale nic nie było istotne, więc oto mój problem:

Chcę przetworzyć łańcuch zawierający tekst HTML. Chcę to zrobić w JavaScript.

Próbowałem tej biblioteki ale wygląda na to, że parsuje HTML mojej bieżącej strony, a nie z ciągu znaków. Ponieważ gdy wypróbuję poniższy kod, zmienia on tytuł mojej strony:

var parser = new HTMLtoDOM("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>", document);

Moim celem jest wyodrębnienie linków z zewnętrznej strony HTML, które czytam jak ciąg znaków.

Czy znasz API żeby to zrobić?

Author: Xufox, 2012-05-14

7 answers

Utwórz atrapę elementu DOM i dodaj do niego ciąg znaków. Następnie można nim manipulować jak każdym elementem DOM.

var el = document.createElement( 'html' );
el.innerHTML = "<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>";

el.getElementsByTagName( 'a' ); // Live NodeList of your anchor elements

Edit: dodanie odpowiedzi jQuery, aby zadowolić fanów!

var el = $( '<div></div>' );
el.html("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>");

$('a', el) // All the anchor elements
 288
Author: Florian Margaine,
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
2015-05-20 17:42:14

To dość proste:

parser=new DOMParser();
htmlDoc=parser.parseFromString(txt, "text/html");
// do whatever you want with htmlDoc.getElementsByTagName('a');

Zgodnie z MDN , aby to zrobić w chrome musisz parsować jako XML tak:

parser=new DOMParser();
htmlDoc=parser.parseFromString(txt, "text/xml");
// do whatever you want with htmlDoc.getElementsByTagName('a');

Jest obecnie nieobsługiwany przez webkit i musisz podążać za odpowiedzią Floriana, a nie wiadomo, czy działa w większości przypadków na przeglądarkach mobilnych.

Edit: teraz szeroko wspierane

 140
Author: Cilan,
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
2018-05-03 02:23:37

EDIT: poniższe rozwiązanie dotyczy tylko "fragmentów" HTML, ponieważ html, head i body są usuwane. Myślę, że rozwiązaniem tego pytania jest metoda Parsefromstring () Domparsera.


Dla fragmentów HTML, rozwiązania wymienione tutaj działają dla większości HTML, jednak w niektórych przypadkach nie będą działać.

Na przykład spróbuj parsować <td>Test</td>. To nie zadziała na div.innerHTML solution ani DOMParser.prototyp.parseFromString nor range.createContextualFragment solution. Tag td idzie brakuje i pozostaje tylko tekst.

Tylko jQuery dobrze radzi sobie z tą sprawą.

Więc rozwiązaniem przyszłości (MS Edge 13+) jest użycie tagu szablonu:

function parseHTML(html) {
    var t = document.createElement('template');
    t.innerHTML = html;
    return t.content.cloneNode(true);
}

var documentFragment = parseHTML('<td>Test</td>');

Dla starszych przeglądarek rozpakowałem metodę jQuery parseHTML () do niezależnego gist - https://gist.github.com/Munawwar/6e6362dbdf77c7865a99

 12
Author: Munawwar,
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
2016-10-16 13:07:56
var $doc = new DOMParser().parseFromString($html, "text/html");
$As = $('a', $doc);
 6
Author: Mathieu,
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-05-14 14:18:00

Najszybszym sposobem analizy HTML w Chrome i Firefox jest Range#createContextualFragment:

var range = document.createRange();
range.selectNode(document.body); // required in Safari
var fragment = range.createContextualFragment('<h1>html...</h1>');
var firstNode = fragment.firstChild;

Zalecałbym utworzenie funkcji pomocniczej, która używa createContextualFragment, jeśli jest dostępna, a w przeciwnym razie wraca do innerHTML.

Benchmark: http://jsperf.com/domparser-vs-createelement-innerhtml/3

 5
Author: Joel Richard,
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
2015-02-08 05:15:57

Funkcja parseHTML zwróci:


Kod:

function parseHTML(markup) {
    if (markup.toLowerCase().trim().indexOf('<!doctype') === 0) {
        var doc = document.implementation.createHTMLDocument("");
        doc.documentElement.innerHTML = markup;
        return doc;
    } else if ('content' in document.createElement('template')) {
       // Template tag exists!
       var el = document.createElement('template');
       el.innerHTML = markup;
       return el.content;
    } else {
       // Template tag doesn't exist!
       var docfrag = document.createDocumentFragment();
       var el = document.createElement('body');
       el.innerHTML = markup;
       for (i = 0; 0 < el.childNodes.length;) {
           docfrag.appendChild(el.childNodes[i]);
       }
       return docfrag;
    }
}

Jak używać:

var links = parseHTML('<!doctype html><html><head></head><body><a>Link 1</a><a>Link 2</a></body></html>').getElementsByTagName('a');
 5
Author: John Slegers,
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
2016-02-25 16:08:45

Jeśli jesteś otwarty na używanie jQuery, ma kilka fajnych udogodnień do tworzenia oddzielonych elementów DOM z ciągów HTML. Można je następnie odpytywać za pomocą zwykłych środków, np.:

var html = "<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>";
var anchors = $('<div/>').append(html).find('a').get();

Edit-właśnie zobaczyłem odpowiedź @ Florian, która jest poprawna. To jest w zasadzie dokładnie to, co powiedział, ale z jQuery.

 2
Author: jmar777,
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-05-14 14:17:13