Analizar una cadena HTML con JS


Busqué una solución pero nada era relevante, así que aquí está mi problema:

Quiero analizar una cadena que contenga texto HTML. Quiero hacerlo en JavaScript.

Probé esta biblioteca pero parece que analiza el HTML de mi página actual, no de una cadena. Porque cuando pruebo el siguiente código, cambia el título de mi página:

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

Mi objetivo es extraer enlaces de una página externa HTML que leo como una cadena.

¿Conoces una API ¿para hacerlo?

Author: Xufox, 2012-05-14

7 answers

Cree un elemento DOM ficticio y agregue la cadena a él. Luego, puede manipularlo como cualquier elemento 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

Editar: añadir una respuesta jQuery para complacer a los 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
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-20 17:42:14

Es bastante simple:

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

De acuerdo con MDN, para hacer esto en chrome es necesario analizar como XML de esta manera:

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

Actualmente no es compatible con webkit y tendría que seguir la respuesta de Florian, y se desconoce que funcione en la mayoría de los casos en navegadores móviles.

Editar: Ahora ampliamente soportado

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-03 02:23:37

EDITAR: La solución a continuación es solo para "fragmentos" HTML,ya que se eliminan html, head y body. Supongo que la solución para esta pregunta es el método ParseFromString() de DOMParser.


Para fragmentos HTML, las soluciones enumeradas aquí funcionan para la mayoría de HTML, sin embargo, para ciertos casos no funcionará.

Por ejemplo, intente analizar <td>Test</td>. Este no funcionará en el div.Solución innerHTML ni DOMParser.prototipo.ParseFromString nor range.createContextualFragment solución. La etiqueta td va falta y solo queda el texto.

Solo jQuery maneja bien ese caso.

Así que la solución futura (MS Edge 13+) es usar la etiqueta de plantilla:

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

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

Para navegadores antiguos he extraído el método parseHTML() de jQuery en un gist independiente - 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-14 14:18:00

La forma más rápida de analizar HTML en Chrome y Firefox es el rango # createContextualFragment:

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

Recomendaría crear una función auxiliar que use createContextualFragment si está disponible y que, de lo contrario, vuelva a innerHTML.

Parámetro: 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-08 05:15:57

La siguiente función parseHTML devolverá :

  • A Document cuando el archivo comienza con un doctype.

  • A DocumentFragment cuando su archivo no comienza con un doctype.


El código:

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

Cómo usar :

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-25 16:08:45

Si está abierto a usar jQuery, tiene algunas buenas facilidades para crear elementos DOM separados a partir de cadenas de HTML. Estos pueden ser consultados a través de los medios habituales, por ejemplo:

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

Editar - acabo de ver la respuesta de @Florian que es correcta. Esto es básicamente exactamente lo que dijo, pero con 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-14 14:17:13