将确切的innerHTML恢复为DOM

Ser*_*rca 21 html javascript firefox jquery dom

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

var stringified = document.documentElement.innerHTML
// later, after serializing and deserializing
document.documentElement.innerHTML = stringified
Run Code Online (Sandbox Code Playgroud)

这在一切都很完美时起作用,但是当DOM不符合w3c时,就会出现问题.第一行工作正常,stringified完全匹配DOM.但是当我从(非w3c兼容)恢复时stringified,浏览器会做一些魔术并且生成的DOM与最初的DOM不同.

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

<p><div></div></p>
Run Code Online (Sandbox Code Playgroud)

那么最终的DOM会是这样的

<p></p><div></div><p></p>
Run Code Online (Sandbox Code Playgroud)

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

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

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

<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>
Run Code Online (Sandbox Code Playgroud)

Lou*_*uis 4

如果您需要能够保存和恢复无效的 HTML 结构,您可以通过 XML 来完成。下面的代码来自这个小提琴

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

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 = "";
});
Run Code Online (Sandbox Code Playgroud)

要恢复,您需要创建一个 XML 文档来反序列化您保存的内容,然后将节点添加到您的文档中:

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);
});
Run Code Online (Sandbox Code Playgroud)

使用小提琴,您可以:

  1. 按“添加 LadyGaga...”按钮创建无效 HTML。

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

  3. 按“恢复”可恢复保存的结构。

上面的代码旨在具有通用性。如果可以对要保存的 HTML 结构做出一些假设,则可以简化代码。例如,blah这不是格式良好的 XML 文档,因为您需要 XML 中的单个顶部元素。所以上面的代码煞费苦心地添加了一个顶级元素(top)来防止这个问题。通常也不可能仅将 HTML 序列化解析为 XML,以便保存操作序列化为 XML。

这是一个概念验证。将 HTML 文档中创建的节点移动到 XML 文档或其他方式可能会产生我没有预料到的副作用。我已经在 Chrome 和 FF 上运行了上面的代码。我手边没有 IE 来运行它。