Analyser une chaîne HTML avec JS

J'ai cherché une solution mais rien n'était pertinent, alors voici mon problème:

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

J'ai essayé cette bibliothèque mais il semble qu'elle analyse le code HTML de ma page actuelle, pas à partir d'une chaîne. Parce que quand j'essaie le code ci-dessous, il change le titre de ma page:

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 but est d'extraire des liens d'une page externe HTML que je lis comme une chaîne.

Connaissez-vous une API pour le faire?

176
demandé sur Xufox 2012-05-14 18:11:11

7 réponses

Créez un élément DOM factice et ajoutez-y la chaîne. Ensuite, vous pouvez le 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 plaire 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
288
répondu Florian Margaine 2015-05-20 17:42:14

C'est assez simple:

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

Selon MDN , pour ce faire dans chrome, vous devez analyser en tant que XML comme suit:

parser=new DOMParser();
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 devrez suivre la réponse de Florian, et il est inconnu de fonctionner dans la plupart des cas sur les navigateurs mobiles.

Edit: maintenant largement pris en charge

140
répondu Cilan 2018-05-03 02:23:37

EDIT: la solution ci-dessous est uniquement pour les "fragments" HTML puisque html,head et body sont supprimés. Je suppose que la solution pour cette question Est la méthode Parsefromstring() de DOMParser.


Pour les fragments HTML, les solutions listées ici fonctionnent pour la plupart des HTML, mais dans certains cas, cela ne fonctionnera pas.

Par exemple, essayez d'analyser <td>Test</td>. Celui-ci ne fonctionnera pas sur la div.solution innerHTML ni DOMParser.prototype.parseFromString ni gamme.createContextualFragment solution. Le tag td va manquant et seul le texte reste.

Seul jQuery gère bien ce cas.

Donc, la future solution (MS Edge 13+) consiste à utiliser la balise template:

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

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

12
répondu Munawwar 2016-10-16 13:07:56
var $doc = new DOMParser().parseFromString($html, "text/html");
$As = $('a', $doc);
6
répondu Mathieu 2012-05-14 14:18:00

Le moyen le plus rapide d'analyser HTML dans Chrome et Firefox est Range#createContextualFragment:

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

Je recommande de créer une fonction d'assistance qui utilise createContextualFragment si disponible et revient à innerHTML sinon.

Référence: http://jsperf.com/domparser-vs-createelement-innerhtml/3

5
répondu Joel Richard 2015-02-08 05:15:57

La fonction suivante parseHTML retournera soit :

  • Un Document lorsque votre fichier commence par un doctype.

  • Un DocumentFragment lorsque votre fichier ne commence pas avec 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;
    }
}

Comment utiliser :

var links = parseHTML('<!doctype html><html><head></head><body><a>Link 1</a><a>Link 2</a></body></html>').getElementsByTagName('a');
5
répondu John Slegers 2016-02-25 16:08:45

Si vous êtes ouvert à l'utilisation de jQuery, il a quelques bonnes installations pour créer des éléments DOM détachés à partir de chaînes de HTML. Ceux-ci peuvent ensuite être interrogés par les moyens habituels, par exemple:

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 - juste vu la réponse de @Florian qui est correcte. C'est essentiellement exactement ce qu'il a dit, mais avec jQuery.

2
répondu jmar777 2012-05-14 14:17:13