363 votes

Analyser une chaîne HTML avec JS

Je veux analyser une chaîne qui contient du texte HTML. Je veux le faire en JavaScript.

J'ai essayé le Bibliothèque d'analyseur HTML en JavaScript pur mais il semble qu'il analyse le HTML de ma page actuelle, et non une chaîne de caractères. Car lorsque j'essaie le code ci-dessous, le titre de ma page est modifié :

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

Mon objectif est d'extraire des liens d'une page HTML externe que je lis comme une chaîne de caractères.

Connaissez-vous une API pour le faire ?

476voto

Florian Margaine Points 16927

Créez un élément DOM fictif et ajoutez-y la chaîne de caractères. Ensuite, vous pouvez la manipuler comme n'importe quel élément 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 : ajout d'une réponse jQuery pour faire plaisir aux fans !

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

338voto

The Wobbuffet Points 3939

C'est très simple :

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

Selon MDN Pour faire cela dans chrome, vous devez analyser le XML comme suit :

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

Il n'est actuellement pas pris en charge par webkit et vous devriez suivre la réponse de Florian, et il est inconnu pour fonctionner dans la plupart des cas sur les navigateurs mobiles.

Edit : Maintenant largement supporté

36voto

Munawwar Points 226

EDIT : La solution ci-dessous ne concerne que les "fragments" HTML puisque html,head et body sont supprimés. Je suppose que la solution à cette question est la méthode parseFromString() de DOMParser :

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

Pour les fragments HTML, les solutions énumérées ici fonctionnent pour la plupart des HTML, mais dans certains cas, elles ne fonctionneront pas.

Par exemple, essayez d'analyser <td>Test</td> . Celui-ci ne fonctionne pas avec la solution div.innerHTML ni avec la solution DOMParser.prototype.parseFromString ni avec la solution range.createContextualFragment. La balise td disparaît et seul le texte reste.

Seul jQuery gère bien ce cas.

La solution future (MS Edge 13+) est donc d'utiliser la balise template :

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

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

Pour les navigateurs plus anciens, j'ai extrait la méthode parseHTML() de jQuery dans un gist indépendant. https://gist.github.com/Munawwar/6e6362dbdf77c7865a99

25voto

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

7voto

John Slegers Points 509

La fonction suivante parseHTML retournera soit :

  • a Document lorsque votre fichier commence par un doctype.

  • a DocumentFragment lorsque votre fichier ne commence pas par un doctype.


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

Mode d'emploi :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X