我想在字符串中包含另一个HTML标记的HTML标记(因此不是DOM元素,普通字符串)。我创建了这个函数,但我想知道如果没有forEach循环我是否可以一次性完成。
这是工作职能:
function style(content) {
var tempStyledContent = content;
var imgMatches = tempStyledContent.match(/(<img.*?src=[\"'](.+?)[\"'].*?>)/g);
imgMatches.forEach(function (imgMatch) {
var imgTag = imgMatch;
var imgSrc = imgMatch.match(/src\s*=\s*"(.+?)"/)[1];
tempStyledContent = tempStyledContent.replace(imgTag,
"<a href=\"" + imgSrc + "\" data-fancybox>" + imgTag + "</a>");
});
return tempStyledContent;
}
参数content
是一个包含HTML代码的字符串。上面的函数输出与输入相同的html,但是包含所有子 img 标签的(fancybox) a 标签。
所以像
这样的输入字符串"<div><img src='example.jpg'/></div>"
将输出
"<div><a href='example.jpg' data-fancybox><img src='example.jpg'/></a></div>"
有人可以改善吗?我对正则表达式知之甚少,以使其更好。
答案 0 :(得分:1)
使用正则表达式操作HTML是notoriously problematic。在DOM解析器中进行简单的更改可能非常难以创建强大的正则表达式;当正则表达式失败时,它会无声地失败,这使错误容易错过。在正则表达式中工作时,您还必须小心处理标记中的所有可能变体,例如空格,属性顺序,引用样式,标记结束样式,类似html但不想要修改的属性内容等。< / p>
正如下面的评论主题中详尽讨论的那样,如果有足够的时间和精力,它肯定可能来处理正则表达式中的所有这些事情;但它导致复杂的,难以维护的正则表达式 - 最重要的是,很难确定你的正则表达式适应每一种可能的有效标记变化。 DOM解析自动处理所有这些内容,并允许您直接使用结构化数据,而不必处理其字符串表示中的所有可能变化。
因此,如果您需要对HTML字符串进行重大更改,最好将HTML转换为真正的DOM树,使用标准DOM方法对其进行操作,然后(如有必要)将其转换回来成一个字符串。幸运的是,它并没有采取大量代码。这是一个简单的香草JS演示:
var htmlToElement = function(html) {
var template = document.createElement('template');
template.innerHTML = html.trim();
return template.content.firstChild;
};
var elementToHtml = function(el) {
return el.outerHTML;
}
// Usage demo:
var string = "<div>This <b>is some</b> <i>html</i><img src='http://example.com'></div>";
var foo = htmlToElement(string);
// perform your DOM manipulation as needed on foo here. This would look much simpler if I wasn't so stubborn about avoiding jQuery these days, but here we are anyway:
foo.querySelectorAll('img').forEach(function(img) {
var link = document.createElement('a');
link.setAttribute('data-fancybox',true);
link.setAttribute('href', img.getAttribute('src'));
img.parentNode.insertBefore(link,img);
link.appendChild(img);
});
// back to a string:
var bar = elementToHtml(foo);
console.log(bar);
&#13;
答案 1 :(得分:0)
好的,我可能会像@DanielBeck建议的那样进行DOM操作。一旦knouckout完成绑定,我将使用$ .wrap http://api.jquery.com/wrap/进行操作。我只是希望没有使用jquery有一个简单的方法,所以如果有其他建议请评论它们。
答案 2 :(得分:-2)
更新
刮刀系列
关于此正则表达式的一些额外信息。
src
属性,同时保留标记结构作为整体。 此正则表达式是解析正则表达式的较大标记的子集 经过多年精心设计和测试 这种设计不可能发生灾难性的回溯 我用这个表格标记了任何答案 Scraper-Series 。
的更新强>
这没有必要,但如果有任何问题,3个可能的img
标签关闭
被考虑在内(如果这是你可能需要的东西)。
正则表达式mod(最后):
已移除/>
添加了>(?:\s*</img\s*>)?
你去了,它处理这三个可能的关闭
(如果使用正确的(x)html / xml处理器,则所有都有效),
这取决于您的使用情况。
<img src='example.jpg'>
<img src='example.jpg'></img>
<img src='example.jpg'/>
查找:/<img(?=(?:[^>"']|"[^"]*"|'[^']*')*?\ssrc\s*=\s*(?:(['"])\s*((?:(?!\1)[\S\s])*?)\s*\1))\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>(?:\s*<\/img\s*>)?/g
替换:<a href=$1$2$1 data-fancybox>$0</a>
https://regex101.com/r/H8msrT/1
可读版本:
<img
(?=
(?: [^>"'] | " [^"]* " | ' [^']* ' )*?
\s src \s* = \s*
(?:
( ['"] ) # (1)
\s*
( # (2 start)
(?:
(?! \1 )
[\S\s]
)*?
) # (2 end)
\s* \1
)
)
\s+
(?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
>
(?:
\s*
</img \s* >
)?