用JS解析HTML字符串

时间:2012-05-14 14:11:12

标签: javascript html dom html-parsing

我搜索了一个解决方案,但没有任何相关内容,所以这是我的问题:

我想解析一个包含HTML文本的字符串。我想用JavaScript做。

我尝试了this library,但似乎它解析了当前页面的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来做吗?

12 个答案:

答案 0 :(得分:317)

创建一个虚拟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

答案 1 :(得分:172)

这很简单:

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

According to MDN,要在chrome中执行此操作,您需要解析为XML,如下所示:

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

它目前不受webkit的支持,您必须遵循Florian的回答,并且在大多数情况下在移动浏览器上工作是未知的。

编辑:现在得到广泛支持

答案 2 :(得分:14)

编辑:以下解决方案仅适用于HTML&#34;片段&#34;因为html,头部和身体都被删除了。我想这个问题的解决方案是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()方法提取到一个独立的要点 - https://gist.github.com/Munawwar/6e6362dbdf77c7865a99

答案 3 :(得分:7)

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

答案 4 :(得分:6)

以下函数parseHTML将返回:


代码:

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

答案 5 :(得分:5)

在Chrome和Firefox中解析HTML的最快方法是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

答案 6 :(得分:2)

如果您愿意使用jQuery,它有一些很好的工具可以从HTML字符串创建分离的DOM元素。然后可以通过常用方法查询这些内容,例如:

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。

答案 7 :(得分:2)

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

答案 8 :(得分:0)

使用此简单代码,您可以做到这一点:

let el = $('<div></div>');
$(document.body).append(el);
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>`);
console.log(el.find('a[href="test0"]'));

答案 9 :(得分:0)

1种方式

使用document.cloneNode()

性能为:

调用document.cloneNode()大约需要0.224999999999977299012毫秒。

也许还会更多。

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

2种方式

使用document.implementation.createHTMLDocument()

性能为:

调用document.implementation.createHTMLDocument()大约需要0.14000000010128133毫秒。

var t0, t1, html;

t0 = performance.now();
html = document.implementation.createHTMLDocument("test");
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"));

3种方式

使用document.implementation.createDocument()

性能为:

调用document.implementation.createHTMLDocument()大约需要0.14000000010128133毫秒。

var t0 = performance.now();
  html = document.implementation.createDocument('', 'html', 
             document.implementation.createDocumentType('html', '', '')
         );
var t1 = performance.now();

console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")

html.documentElement.innerHTML = '<html><head><title>Test</title></head><body><div id="test1">test</div></body></html>';

console.log(html.getElementById("test1"));

4种方式

使用new Document()

性能为:

调用document.implementation.createHTMLDocument()大约需要0.13499999840860255毫秒。

  • 注意

ParentNode.append是2020年的实验技术。

var t0, t1, html;

t0 = performance.now();
//---------------
html = new Document();

html.append(
  html.implementation.createDocumentType('html', '', '')
);
    
html.append(
  html.createElement('html')
);
//---------------
t1 = performance.now();

console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")

html.documentElement.innerHTML = '<html><head><title>Test</title></head><body><div id="test1">test1</div></body></html>';

console.log(html.getElementById("test1"));

答案 10 :(得分:0)

对我来说。我不得不使用在angular ngx bootstrap popover的popover中解析的元素的innerhtml 这是对我有用的解决方案

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

在构造函数中

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

在 html 中

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

答案 11 :(得分:-1)

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

内容:<center><h1>404 Not Found</h1></center>
结果:"404 Not Found"