Ontleed een HTML-tekenreeks met JS

Ik heb naar een oplossing gezocht, maar niets was relevant, dus hier is mijn probleem:

Ik wil een string ontleden die HTML-tekst bevat. Ik wil het in JavaScript doen.

Ik heb deze bibliotheekgeprobeerd, maar het lijkt erop dat het de HTML van mijn huidige pagina, niet van een string. Want als ik de onderstaande code probeer, verandert de titel van mijn pagina:

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);

Mijn doel is om links uit een externe HTML-pagina te halen die ik lees als een tekenreeks.

Kent u een API om dit te doen?


Antwoord 1, autoriteit 100%

Maak een dummy DOM-element en voeg de string eraan toe. Vervolgens kun je het manipuleren zoals elk DOM-element.

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

Bewerken: een jQuery-antwoord toegevoegd om de fans te plezieren!

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

Antwoord 2, autoriteit 68%

Het is vrij eenvoudig:

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

Volgens MDN, om dit te doen in chrome moet je als XML ontleden, zoals:

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

Het wordt momenteel niet ondersteund door webkit en u moet het antwoord van Florian volgen, en het is in de meeste gevallen niet bekend dat het in mobiele browsers werkt.

Bewerken: nu breed ondersteund


Antwoord 3, autoriteit 6%

EDIT: De onderstaande oplossing is alleen voor HTML “fragmenten” aangezien html,head en body zijn verwijderd. Ik denk dat de oplossing voor deze vraag de parseFromString()-methode van DOMParser is:

const parser = new DOMParser();
const document = parser.parseFromString(html, "text/html");

Voor HTML-fragmenten werken de hier vermelde oplossingen voor de meeste HTML, maar in bepaalde gevallen zal het niet werken.

Probeer bijvoorbeeld <td>Test</td>te ontleden. Deze werkt niet op de div.innerHTML-oplossing, noch op de oplossing DOMParser.prototype.parseFromString of range.createContextualFragment. De td-tag verdwijnt en alleen de tekst blijft over.

Alleen jQuery behandelt die zaak goed.

Dus de toekomstige oplossing (MS Edge 13+) is om een sjabloontag te gebruiken:

function parseHTML(html) {
    var t = document.createElement('template');
    t.innerHTML = html;
    return t.content;
}
var documentFragment = parseHTML('<td>Test</td>');

Voor oudere browsers heb ik de parseHTML()-methode van jQuery geëxtraheerd in een onafhankelijke gist – https://gist .github.com/Munawwar/6e6362dbdf77c7865a99


Antwoord 4, autoriteit 5%

var doc = new DOMParser().parseFromString(html, "text/html");
var links = doc.querySelectorAll("a");

Antwoord 5, autoriteit 2%

De volgende functie parseHTMLretourneert ofwel :

  • een Documentwanneer uw bestand begint met een doctype.

  • een DocumentFragmentwanneer uw bestand niet begint met een doctype.


De code:

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;
    }
}

Hoe te gebruiken:

var links = parseHTML('<!doctype html><html><head></head><body><a>Link 1</a><a>Link 2</a></body></html>').getElementsByTagName('a');

Antwoord 6

De snelste manier om HTML te ontleden in Chrome en Firefox is Range#createContextualFragment:

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

Ik zou aanraden om een helperfunctie te maken die gebruikmaakt van createContextualFragment indien beschikbaar en anders terugvalt op innerHTML.

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


Antwoord 7

Als je openstaat voor het gebruik van jQuery, heeft het een aantal leuke faciliteiten voor het maken van losse DOM-elementen uit strings van HTML. Deze kunnen dan op de gebruikelijke manier worden opgevraagd, bijvoorbeeld:

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();

Bewerken – ik zag zojuist het antwoord van @Florian dat correct is. Dit is eigenlijk precies wat hij zei, maar dan met jQuery.


Antwoord 8

const parse = Range.prototype.createContextualFragment.bind(document.createRange());
document.body.appendChild( parse('<p><strong>Today is:</strong></p>') ),
document.body.appendChild( parse(`<p style="background: #eee">${new Date()}</p>`) );


Alleen geldige onderliggende Nodeen binnen de bovenliggende Node(begin van het Range) worden geparseerd. Anders kunnen er onverwachte resultaten optreden:

// <body> is "parent" Node, start of Range
const parseRange = document.createRange();
const parse = Range.prototype.createContextualFragment.bind(parseRange);
// Returns Text "1 2" because td, tr, tbody are not valid children of <body>
parse('<td>1</td> <td>2</td>');
parse('<tr><td>1</td> <td>2</td></tr>');
parse('<tbody><tr><td>1</td> <td>2</td></tr></tbody>');
// Returns <table>, which is a valid child of <body>
parse('<table> <td>1</td> <td>2</td> </table>');
parse('<table> <tr> <td>1</td> <td>2</td> </tr> </table>');
parse('<table> <tbody> <td>1</td> <td>2</td> </tbody> </table>');
// <tr> is parent Node, start of Range
parseRange.setStart(document.createElement('tr'), 0);
// Returns [<td>, <td>] element array
parse('<td>1</td> <td>2</td>');
parse('<tr> <td>1</td> <td>2</td> </tr>');
parse('<tbody> <td>1</td> <td>2</td> </tbody>');
parse('<table> <td>1</td> <td>2</td> </table>');

Antwoord 9

Eenrichtingsverkeer

Gebruik document.cloneNode()

Prestatie is:

Oproep naar document.cloneNode()duurde ~0.22499999977299012 milliseconden.

en misschien zullen er meer zijn.

var t0, t1, html;
t0 = performance.now();
   html = document.cloneNode(true);
t1 = performance.now();
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")
html.documentElement.innerHTML = '<!DOCTYPE html><html><head><title>Test</title></head><body><div id="test1">test1</div></body></html>';
console.log(html.getElementById("test1"));

Antwoord 10

voor mij. ik moest innerhtml gebruiken van een element dat is geparseerd in popover van hoekige ngx bootstrap popover
dit is de oplossing die voor mij werkte

public htmlContainer = document.createElement( 'html' );

in constructor

this.htmlContainer.innerHTML = ''; setTimeout(() => { this.convertToArray(); });

convertToArray() {
    const shapesHC = document.getElementsByClassName('weekPopUpDummy');
    const shapesArrHCSpread = [...(shapesHC as any)];
    this.htmlContainer = shapesArrHCSpread[0];
    this.htmlContainer.innerHTML = shapesArrHCSpread[0].textContent;
  }

in html

<div class="weekPopUpDummy" [popover]="htmlContainer.innerHTML" [adaptivePosition]="false" placement="top" [outsideClick]="true" #popOverHide="bs-popover" [delay]="150" (onHidden)="onHidden(weekEvent)" (onShown)="onShown()">

Antwoord 11

let content = "<center><h1>404 Not Found</h1></center>"
let result = $("<div/>").html(content).text()

content: <center><h1>404 Not Found</h1></center>,
resultaat: "404 Not Found"

Other episodes