安全地将HTML转换为JSON的方法是什么?

3
我的问题很简单,我想用json重建一个html页面,但我不想破坏现有的html、框架等...
例子:
var myDiv = { tag : "div", style : "color:blue", class : "jj", content : "Hello"};

var myDiv = { tag : "div", style : "color:blue", class : "jj", content : "Hello"};
var param = { forbid : { tag : true, content : true } };
var createTag = function(o) {

    var node = document.createElement(o.tag);
    for (att in o) {
      if (!param.forbid[att]) node.setAttribute(att, o[att]);
    }
    node.appendChild(document.createTextNode(o.content))
    return node;

}


document.body.textContent = createTag(myDiv).outerHTML;

这段代码的结果是:
<div style="color:blue" class="jj"> Hello </div>

我怎样才能确保“标签”和“内容”不会影响现有/未来的属性?并且保持简单易懂?


3
你为什么想要这样做,而不是直接编写HTML呢? - Hylianpuffball
看看 hoquet 这个项目 https://github.com/tjb1982/hoquet,也许这正是你需要的。 - Anton Harald
1
这似乎是“不简单”的最恰当定义。 - ceejayoz
请在您的问题中包含您尝试过的代码以及遇到的问题。目前这是一个“给我代码”的风格问题,应该被关闭为太宽泛或不适合主题(#1),因为它没有提供最小可重现示例(MCVE)。 - zzzzBov
@zzzzBov 我刚刚有一个可用的代码片段。 - alexino2
2个回答

9
为避免与属性冲突,我建议将它们分开。
var myDiv = {
  tagName: "div",
  attributes: {
    style: "color: blue",
    class: "jj"
  },
  childNodes: ["Hello"]
};

function parseTree(node) {
  if(typeof node === 'string') // Text node
    return document.createTextNode(node);
  // Otherwise, assuming an element. Consider adding
  // `node.nodeType` if you want multiple node types
  var el = document.createElement(node.tagName);
  if(node.hasOwnProperty('attributes'))
    for(var attr in node.attributes)
      if(node.attributes.hasOwnProperty(attr))
        el.setAttribute(attr, node.attributes[attr]);
  if(node.hasOwnProperty('childNodes'))
    node.childNodes.forEach(function(child) {
      el.appendChild(parseTree(child));
    });
  return el;
}
document.body.textContent = parseTree({
  tagName: "div",
  attributes: {
    style: "color: blue",
    class: "jj"
  },
  childNodes: ["Hello"]
}).outerHTML;

或者,您可以使用一些不允许在属性名称中使用的字符来表示字符串。例如,\u0000

var myDiv = {
  " tagName": "div",
  style: "color: blue",
  class: "jj",
  " childNodes": ["Hello"]
};

function parseTree(node) {
  if(typeof node === 'string') // Text node
    return document.createTextNode(node);
  // Otherwise, assuming an element. Consider adding
  // `node[" nodeType"]` if you want multiple node types
  var el = document.createElement(node[" tagName"]);
  for(var attr in node)
    if(node.hasOwnProperty(attr) && attr[0] !== " ")
      el.setAttribute(attr, node[attr]);
  if(node[" childNodes"])
    node[" childNodes"].forEach(function(child) {
      el.appendChild(parseTree(child));
    });
  return el;
}
document.body.textContent = parseTree({
  " tagName": "div",
  style: "color: blue",
  class: "jj",
  " childNodes": ["Hello"]
}).outerHTML;


2
@alexino2 如果你想允许任意属性,这是唯一的选项。 - Oriol
parseTree 大致上是我用来将其转换为 HTML 的工具,但仅仅使用“attributes: {}”这一事实使得事情变得安全了,但并不简单... - alexino2
现在的代码 p1.p2.myDiv.attributes.style = "" 比起 p1.p2.myDiv.style = "" 更加复杂。 - alexino2
@Oriol Symbol看起来很棒,但它是ES6的,并且似乎不兼容高级压缩(它讨厌字符串)。我想最终我会坚持使用属性...因为这更加通用。再次感谢。 - alexino2
@penne12 当然,符号在这里没有用处。这就是当我试图改进一个答案但太困时会发生的事情。谢谢。 - Oriol
显示剩余8条评论

-1
你可以尝试这样做,如果你愿意的话:
["div", {style: "color:blue", class: "jj"}, ["Hello"]]

如果有一个内部元素,你可以这样做:

["div", {style: "color:blue", class: "jj"}, [[
  "p",
  "hello"
]]]

这是解析代码(仅包括parseTree函数)- 我还添加了一种尝试它的方法(HTML是使用基于JSON格式的示例编写的)。

html = ["div", [["div",
  [
    ["p", ["Try it out:"]],
    [
      "code", {
        id: "try",
        style: "display:block",
        contentEditable: true
      },
      ['["div", { style: "color:blue;", class: "jj"}, ["Hello"]]']
    ],
    ["button", {
        "onclick": "return tryOut();"
      },
      ["Run"]
    ]
  ]
],["div", {id: "result-wrapper"}]]]

window.tryOut = function() {
  var el = parseTree(eval(document.querySelector("code#try").innerText));
  var holder = document.createElement("div");
  holder.appendChild(el);
  document.querySelector("#result-wrapper").innerHTML = holder.innerHTML;
}

document.body.appendChild(parseTree(html));


function parseTree(tree) {
  if (typeof tree === 'string') {
    return document.createTextNode(tree);
  }

  var el = document.createElement(tree[0]),
    attrs, simple, inner;

  if (tree.length == 2) {
    if (Array.isArray(tree[1])) {
      inner = tree[1];
    } else {
      attrs = tree[1];
    }
  } else if (tree.length == 3) {
    attrs = tree[1];
    inner = tree[2];
  } else {
    simple = true;
  }

  if (!simple) {
    if (attrs) {
      for (var attr in attrs)
        if (attrs.hasOwnProperty(attr)) {
          console.log(attr)
          console.log(attrs[attr])
          el.setAttribute(attr, attrs[attr]);
        }
    }
    if (inner) {
      inner.forEach(function(child) {
        el.appendChild(parseTree(child));
      });
    }
  }

  return el;
}

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接