使用另一个HTML标记

时间:2018-05-31 16:57:21

标签: javascript regex

我想在字符串中包含另一个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>"

有人可以改善吗?我对正则表达式知之甚少,以使其更好。

3 个答案:

答案 0 :(得分:1)

使用正则表达式操作HTML是notoriously problematic。在DOM解析器中进行简单的更改可能非常难以创建强大的正则表达式;当正则表达式失败时,它会无声地失败,这使错误容易错过。在正则表达式中工作时,您还必须小心处理标记中的所有可能变体,例如空格,属性顺序,引用样式,标记结束样式,类似html但不想要修改的属性内容等。< / p>

正如下面的评论主题中详尽讨论的那样,如果有足够的时间和精力,它肯定可能来处理正则表达式中的所有这些事情;但它导致复杂的,难以维护的正则表达式 - 最重要的是,很难确定你的正则表达式适应每一种可能的有效标记变化。 DOM解析自动处理所有这些内容,并允许您直接使用结构化数据,而不必处理其字符串表示中的所有可能变化。

因此,如果您需要对HTML字符串进行重大更改,最好将HTML转换为真正的DOM树,使用标准DOM方法对其进行操作,然后(如有必要)将其转换回来成一个字符串。幸运的是,它并没有采取大量代码。这是一个简单的香草JS演示:

&#13;
&#13;
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;
&#13;
&#13;

答案 1 :(得分:0)

好的,我可能会像@DanielBeck建议的那样进行DOM操作。一旦knouckout完成绑定,我将使用$ .wrap http://api.jquery.com/wrap/进行操作。我只是希望没有使用jquery有一个简单的方法,所以如果有其他建议请评论它们。

答案 2 :(得分:-2)

更新

刮刀系列

关于此正则表达式的一些额外信息。

  • 首先,这不解析HTML,只有特殊的DOM解析器可以做到这一点。
  • 它匹配任何位置的src属性,同时保留标记结构作为整体。
  • 它会记住属性值引用。
  • 它可用于查找特定值。
  • 这是一个同时找到众多att-val的模板。
  • 找到att-val的 OUT-OF-ORDER

此正则表达式是解析正则表达式的较大标记的子集 经过多年精心设计和测试 这种设计不可能发生灾难性的回溯 我用这个表格标记了任何答案 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* >
 )?