JavaScript修复坏的HTML标签

时间:2013-01-04 10:47:01

标签: javascript sharepoint

我正在使用Sharepoint网站。我无权访问webparts代码。我只能用JavaScript更改母版页。

其中一个webpart有一个bug。它会将<img>更改为错误的SRC值。

示例:

应该有

<img alt="img" src="http://www.apicture.png" style="margin:5px" /><br /><br />

但有

<img alt="img" src="<a href="http://www.apicture.png">http://www.apicture.png</a>" style="margin:5px" /><br /><br />

我尝试匹配和替换,但是innerHtml打破了其他脚本。

如何用JavaScript修复我?

编辑:

我有代码:

var markup = document.documentElement.innerHTML;
markup = markup.replace(/src=\".*?(http:\/\/[^\"]+)\"/g,'src=\"$1\"');
document.documentElement.innerHTML = markup;

但它打破了我的网页。

2 个答案:

答案 0 :(得分:5)

由于DOM已被破坏,您需要退后一步并尝试抢救HTML。

1)找到破碎元素的父母。虽然document.body.innerHTML内的搜索和替换可能会有效,you shouldn't really let regexes anywhere near large chunks of HTML。性能也是一个问题,尽管是较小的一个。

<img alt="img" src="<a href="http://...将被浏览器解析为具有源“<a href=”的图像。

使用jQuery,您只需要$('img[src="<a href"]')来获取图像。除IE&lt; 8外,您可以将querySelectorAll与相同的选择器一起使用。如果您没有jQuery,并且想要支持IE7,则需要使用getElementsByTagName进行手动过滤。

如果你真的很幸运,你可以通过getElementByID(或等效的jQuery)找到父母。

这很容易。


2)您的HTML无法验证,浏览器已经做了一些努力来修复它。你需要扭转这个过程。预测浏览器操作是有问题的,但让我们尝试。

让我们看一下浏览器的功能

<img src="<a href="http://www.test.com/img/image-20x20.png">http://www.test.com/img/image-20x20.png</a>" style="margin:5px" />​

这是Chrome和Firefox修复它的方式:

<img src="&lt;a href=" http:="" www.test.com="" img="" image-20x20.png"="">http://www.test.com/img/image-20x20.png" style="margin:5px" /&gt;

IE9在img(o_0)中按字母顺序对innerHTML内的属性进行排序,并且不在HTML中转义src中的<。 IE7-8还从属性中剥离=""

图像属性难以挽救,但文字内容没有受到伤害。无论如何,可以看到模式:

应该保留从<img开始直到src=的所有内容。不幸的是,在IE中,参数被重新排列,因此您还必须保留不正确的标记。必须删除src="..."本身。在现代浏览器中,过去的所有内容都是[不正确],但在IE中,正确的属性可能会在那里悄然发生(反之亦然)。然后图像标签结束。

以下所有内容都是真正的URL,直到双引号。从双引号到HTML转义/>是属于图像标记的属性。我们希望他们不包含HTML。 CSS很好(为了我们的目的)。


3)让我们构建正则表达式:一个开放的IMG标记,任何属性(让希望它们不包含HTML)(捕获),src属性及其特定值(转义或未转义),任何其他属性(已捕获),标记结束,URL(已捕获),更多属性(已捕获)以及HTML转义结束标记。

/<img([^>]*?)src="(?:<|\&lt\;)a href="([^>]*?)>([^"]+?)"(.*?)\/&gt;/gi

您可能对how it's seen by RegexPal.com感兴趣。


它应该被替换为:具有连接的适当属性的图像,以及被抢救的src。过滤属性可能是值得的,所以让我们选择回调替换。普通属性的键中只包含单词字符。更重要的是,普通属性通常是非空字符串(IMG标记没有布尔属性,unless you are using server-side maps)。这将匹配所有空属性,但不匹配有效的属性键:/\S+(?:="")?(?!=)/


以下是代码:

//forEach, indexOf, map need shimming in IE<9
//querySelectorAll cannot be reliably shimmed, so I'm not using that.

//author: Jan Dvorak
// https://stackoverflow.com/a/14157761/499214

var images = document.getElementsByTagName("img");
var parents = [];
[].forEach.call(images, function(i){
  if(
    /(?:<|\&lt\;)a href=/.test(i.getAttribute("src"))
    && !~parents.indexOf(i.parentNode)
  ){ 
    parents.push(i.parentNode)
  }
})

var re = /<img([^>]*?)src="(?:<|\&lt\;)a href="([^>]*?)>([^"]+?)"(.*?)\/&gt;/gi;
parents.forEach(function(p){
  p.innerHTML = p.innerHTML.replace(
    re, 
    function(match, attr1, attr2, url, attr3){
      var attrs = [attr1, attr2, attr3].map(function(a){
        return a.replace(/\S+(?:="")?(?!=)/g,"");
      }).join(" ");
      return '<img '+attrs+' src="'+url+'" />';
    }
  );
});

小提琴:http://jsfiddle.net/G2yj3/1/

答案 1 :(得分:1)

您可以使用正则表达式修复src属性,但不会修复整个页面。原因是Web浏览器试图解析这样糟糕的HTML并在执行JS之前产生奇怪的输出(额外的元素等)。由于您不能干扰HTML解析/呈现引擎,除了更改原始内容以解决此问题之外,没有其他合理的方法。