【问题标题】:How to convert HTML to valid XHTML?如何将 HTML 转换为有效的 XHTML?
【发布时间】:2012-08-19 00:32:01
【问题描述】:

我有一个 HTML 字符串,在这个例子中它看起来像

<img src="somepic.jpg" someAtrib="1" >

我正在尝试锻炼一个匹配“img”节点的正则表达式,并在节点末尾应用一个斜线,使其看起来像。

<img src="somepic.jpg" someAtrib="1" />

这里的最终目标基本上是确保节点是关闭的,打开的节点在 HTML 中有效,但显然不是 XML。有没有正则表达式爱好者可以提供帮助?

【问题讨论】:

  • 你不应该parse (X)HTML with regex.。 HTML 不是正则的,因此不适合正则表达式。使用成熟的 HTML 解析器。
  • @DavidB 我明白你在说什么。但是我试图操纵一个“字符串”,这就是我问这个问题的原因:)
  • 原始标记无效,请求的 XHTML 标记也无效。您的意思是“格式良好”而不是“有效”吗?

标签: javascript html xml parsing xhtml


【解决方案1】:

不要使用正则表达式,而是使用专用的解析器。在 JavaScript 中,使用DOMParser 创建一个文档,然后使用XMLSerializer 对其进行序列化:

var doc = new DOMParser().parseFromString('<img src="foo">', 'text/html');
var result = new XMLSerializer().serializeToString(doc);
// result:
// <html xmlns="http://www.w3.org/1999/xhtml"><head></head><body> (no line break)
// <img src="foo" /></body></html>

如果您需要将其与 nodejs 后端一起使用,则必须使用 xmldomnpm i xmldom.

【讨论】:

  • 嘿,罗伯。我想学习如何使用这种技术。我正在运行 Opera9、IE6 和 FF2(我的所有代码都必须在旧版浏览器上运行以实现向后兼容性)并且上面的代码不能按原样运行。还需要包括什么才能使其正常工作?你能发布一个完整的工作功能吗?谢谢。
  • @ridgerunner IE9+, FF 12+ (4+ with DOMParser text/html polyfill), Opera 11.6+ (w/ DOMParser polyfill) 支持。 Chrome (21) 有一个错误,即未添加 /&gt;。对不起,我没有详细说明,我很忙atm。如果您愿意,请随时编辑我/您的答案,使其更完整。
  • 在 Chrome (34) 中仍然无法使用,所以这是一项很酷的技术,但如果您的用户使用的是 Chrome,则不然。
【解决方案2】:

除了 Rob W 的answer,还可以使用 RegEx 提取正文内容:

var doc = new DOMParser().parseFromString('<img src="foo">', 'text/html');
var result = new XMLSerializer().serializeToString(doc);

/<body>(.*)<\/body>/im.exec(result);
result = RegExp.$1;

// result:
// <img src="foo" />

注意:parseFromString(htmlString, 'text/html'); 会在 IE9 中引发错误,因为 text/html mimeType 不是 supported in IE9。不过适用于 IE10 和 IE11。

【讨论】:

  • 为什么使用正则表达式?您可以简单地使用 doc.body.innterHTML
  • 纠正自己。例如,innerHTML 将返回
    而不是
    。但是这种正则表达式模式效果更好stackoverflow.com/questions/3628374/…
【解决方案3】:

您可以创建 xhtml 文档并导入/采用 html 元素。 HTML 字符串可以由 HTMLElement.innerHTML 属性解析,原因。 关键是使用 Document.importNode() 或 Document.adoptNode() 方法来转换 html 节点到 xhtml 节点:

var di = document.implementation;
var hd = di.createHTMLDocument();
var xd = di.createDocument('http://www.w3.org/1999/xhtml', 'html', null);
hd.body.innerHTML = '<img>';
var img = hd.body.firstElementChild;
var xb = xd.createElement('body');
xd.documentElement.appendChild(xb);
console.log('html doc:\n' + hd.documentElement.outerHTML + '\n');
console.log('xhtml doc:\n' + xd.documentElement.outerHTML + '\n');
img = xd.importNode(img); //or xd.adoptNode(img). Now img is a xhtml element
xb.appendChild(img);
console.log('xhtml doc after import/adopt img from html:\n' + xd.documentElement.outerHTML + '\n');

输出应该是:

html doc:
<html><head></head><body><img></body></html>

xhtml doc:
<html xmlns="http://www.w3.org/1999/xhtml"><body></body></html>

xhtml doc after import/adopt img from html:
<html xmlns="http://www.w3.org/1999/xhtml"><body><img /></body></html>

Rob W 的答案在 chrome(至少 29 及以下)中不起作用,因为 DOMParser 不支持 'text/html' 类型,并且 XMLSerializer 为 chrome 中的 html 文档生成 html 语法(不是 xhtml)。

【讨论】:

  • 这似乎是比 Rob W 更好的解决方案。 importNode() 有第二个参数,如果你还想转换后代元素
【解决方案4】:

这会做得很好:

result = text.replace(/(<img\b[^<>]*[^<>\/])>/ig, "$1 />");

附录:如果(不太可能)您的代码包含包含尖括号的标记属性(这不是有效的 XML/XHTML BTW),那么这个会做得更好:

result = text.replace(/(<img\b(?:[^<>"'\/]+|'[^']*'|"[^"]*")*)>/ig, "$1 />");

【讨论】:

  • @John 正则表达式必须用于创建符合 XHTML 的文档的原因是它不可靠。例如,这个答案已经在&lt;img alt="2 &gt; 1" src="2gt1"&gt; 失败了。输出为&lt;img alt="2 /&gt; 1" src="2gt1"&gt;
猜你喜欢
  • 2014-03-30
  • 2010-09-13
  • 2021-11-17
  • 1970-01-01
  • 2016-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多