将确切的innerHTML还原到DOM [英] Restore exact innerHTML to DOM

查看:353
本文介绍了将确切的innerHTML还原到DOM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想保存DOM的html字符串,然后将其恢复为完全相同.代码看起来像这样:

I'd like to save the html string of the DOM, and later restore it to be exactly the same. The code looks something like this:

var stringified = document.documentElement.innerHTML
// later, after serializing and deserializing
document.documentElement.innerHTML = stringified

这在一切都完美的情况下有效,但是当DOM不符合w3c标准时,就会出现问题.第一行工作正常,stringified与DOM完全匹配.但是,当我从(不兼容w3c的)stringified恢复时,浏览器做了一些魔术,结果得到的DOM与原来的不一样.

This works when everything is perfect, but when the DOM is not w3c-comliant, there's a problem. The first line works fine, stringified matches the DOM exactly. But when I restore from the (non-w3c-compliant) stringified, the browser does some magic and the resulting DOM is not the same as it was originally.

例如,如果我的原始DOM看起来像

For example, if my original DOM looks like

<p><div></div></p>

然后最终的DOM看起来像

then the final DOM will look like

<p></p><div></div><p></p>

,因为不允许将div元素包含在p元素内.有什么方法可以使浏览器使用与页面加载时相同的html解析并按原样接受损坏的html?

since div elements are not allowed to be inside p elements. Is there some way I can get the browser to use the same html parsing that it does on page load and accept broken html as-is?

为什么html首先被破坏? DOM不是由我控制.

Why is the html broken in the first place? The DOM is not controlled by me.

这是显示行为 http://jsfiddle.net/b2x7rnfm/5/的jsfiddle.打开控制台.

Here's a jsfiddle to show the behavior http://jsfiddle.net/b2x7rnfm/5/. Open your console.

<body>
    <div id="asdf"><p id="outer"></p></div>
    <script type="text/javascript">
        var insert = document.createElement('div');
        var text = document.createTextNode('ladygaga');
        insert.appendChild(text);
        document.getElementById('outer').appendChild(insert);
        var e = document.getElementById('asdf')
        console.log(e.innerHTML);
        e.innerHTML = e.innerHTML;
        console.log(e.innerHTML); // This is different than 2 lines above!!
    </script>
</body>

推荐答案

如果您需要能够保存和恢复无效的HTML结构,则可以通过XML来实现.以下代码来自此小提琴.

If you need to be able to save and restore an invalid HTML structure, you could do it by way of XML. The code which follows comes from this fiddle.

要保存,请创建一个新的XML文档,并向其中添加要序列化的节点:

To save, you create a new XML document to which you add the nodes you want to serialize:

var asdf = document.getElementById("asdf");
var outer = document.getElementById("outer");
var add = document.getElementById("add");
var save = document.getElementById("save");
var restore = document.getElementById("restore");

var saved = undefined;
save.addEventListener("click", function () {
  if (saved !== undefined)
    return; /// Do not overwrite

  // Create a fake document with a single top-level element, as 
  // required by XML.    
  var parser = new DOMParser();
  var doc = parser.parseFromString("<top/>", "text/xml");

  // We could skip the cloning and just move the nodes to the XML
  // document. This would have the effect of saving and removing 
  // at the same time but I wanted to show what saving while 
  // preserving the data would look like    
  var clone = asdf.cloneNode(true);
  var top = doc.firstChild;
  var child = asdf.firstChild;
  while (child) {
    top.appendChild(child);
    child = asdf.firstChild;
  }
  saved = top.innerHTML;
  console.log("saved as: ", saved);

  // Perform the removal here.
  asdf.innerHTML = "";
});

要还原,请创建一个XML文档以反序列化保存的内容,然后将节点添加到文档中:

To restore, you create an XML document to deserialize what you saved and then add the nodes to your document:

restore.addEventListener("click", function () {
  if (saved === undefined)
      return; // Don't restore undefined data!

  // We parse the XML we saved.
  var parser = new DOMParser();
  var doc = parser.parseFromString("<top>" + saved + "</top>", "text/xml");
  var top = doc.firstChild;

  var child = top.firstChild;
  while (child) {
    asdf.appendChild(child);
    // Remove the extra junk added by the XML parser.
    child.removeAttribute("xmlns");
    child = top.firstChild;
  }
  saved = undefined;
  console.log("inner html after restore", asdf.innerHTML);
});

使用小提琴,您可以:

  1. 按下添加LadyGaga ..."按钮以创建无效的HTML.

  1. Press the "Add LadyGaga..." button to create the invalid HTML.

按保存并从文档中删除"以将结构保存在asdf中并清除其内容.这会将保存的内容打印到控制台.

Press "Save and Remove from Document" to save the structure in asdf and clear its contents. This prints to the console what was saved.

按恢复"以恢复保存的结构.

Press "Restore" to restore the structure that was saved.

上面的代码旨在具有通用性.如果可以对要保存的HTML结构做出一些假设,则可以简化代码.例如,blah并不是格式正确的XML文档,因为您需要XML中的单个top元素.因此,上面的代码会尽力添加顶级元素(top)以防止出现此问题.通常也不能仅将HTML序列化解析为XML,这样保存操作就序列化为XML.

The code above aims to be general. It would be possible to simplify the code if some assumptions can be made about the HTML structure to be saved. For instance blah is not a well-formed XML document because you need a single top element in XML. So the code above takes pains to add a top-level element (top) to prevent this problem. It is also generally not possible to just parse an HTML serialization as XML so the save operation serializes to XML.

这是概念证明,比什么都重要.从HTML文档中创建的节点移动到XML文档或其他未曾想到的方式可能会产生副作用.我已经在Chrome和FF上运行了上面的代码.我没有IE可以在那儿运行它.

This is a proof-of-concept more than anything. There could be side-effects from moving nodes created in an HTML document to an XML document or the other way around that I have not anticipated. I've run the code above on Chrome and FF. I don't have IE at hand to run it there.

这篇关于将确切的innerHTML还原到DOM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆