Разбор строки HTML с помощью JS

Я искал решение, но ничего не значимо, поэтому вот моя проблема:

Я хочу проанализировать строку, содержащую текст HTML. Я хочу сделать это в JavaScript.

Я пробовал эту библиотеку, но кажется, что она анализирует HTML моей текущей страницы, а не из строки. Потому что, когда я пытаюсь выполнить код ниже, он меняет название моей страницы:

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

Моя цель - извлечь ссылки с внешней страницы HTML, которую я читаю, как строку.

Вы знаете API для этого?

Ответ 1

Создайте фиктивный элемент DOM и добавьте к нему строку. Затем вы можете манипулировать им, как любой элемент 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

Изменить: добавив ответ jQuery, чтобы понравиться фанатам!

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

Ответ 2

Это довольно просто:

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

Согласно MDN, чтобы сделать это в Chrome, вам нужно проанализировать как XML так:

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

В настоящее время он не поддерживается webkit, и вам придется следовать ответу Florian, и в большинстве случаев он неизвестен для мобильных браузеров.

Изменение: теперь широко поддерживается

Ответ 3

EDIT: нижеприведенное решение предназначено только для HTML-фрагментов, поскольку html, head и body удаляются. Я думаю, решение для этого вопроса - метод DOMParser parseFromString().


Для фрагментов HTML решения, перечисленные здесь, работают для большинства HTML, однако в некоторых случаях это не сработает.

Например, попробуйте разбор <td>Test</td>. Этот не будет работать с решением div.innerHTML, а не с DOMParser.prototype.parseFromString или range.createContextualFragment. Тег td пропадает, и остается только текст.

Только jQuery обрабатывает этот случай.

Итак, в будущем решение (MS Edge 13+) должно использовать тег шаблона:

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

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

Для старых браузеров я извлек метод jQuery parseHTML() в независимый gist - https://gist.github.com/Munawwar/6e6362dbdf77c7865a99

Ответ 4

var $doc = new DOMParser().parseFromString($html, "text/html");
$As = $('a', $doc);

Ответ 5

Следующая функция parseHTML возвратит либо:

  • Document когда ваш файл начинается с типа документа.

  • DocumentFragment когда ваш файл не начинается с типа документа.


Код:

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

Как пользоваться:

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

Ответ 6

Самый быстрый способ анализа HTML в Chrome и Firefox - это Range # createContextualFragment:

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

Я бы рекомендовал создать вспомогательную функцию, которая использует createContextualFragment, если она доступна, и возвращается в innerHTML в противном случае.

Контрольный показатель: http://jsperf.com/domparser-vs-createelement-innerhtml/3

Ответ 7

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


Только допустимый дочерний Node в родительском Node (начало Range) будет проанализирован. В противном случае могут возникнуть неожиданные результаты:
// <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>');

Ответ 8

Если вы открыты для использования jQuery, у него есть хорошие возможности для создания отдельных элементов DOM из строк HTML. Затем их можно запросить с помощью обычных средств, например:

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

Изменить - просто увидел @Florian ответ, который является правильным. Это в основном то, что он сказал, но с jQuery.

Ответ 9

(adsbygoogle = window.adsbygoogle || []). push ({google_ad_client: "ca-pub-3323261257580508", enable_page_level_ads: true});