Javascript 从html到json文件的异常转换

Javascript 从html到json文件的异常转换,javascript,json,Javascript,Json,我有一个POC要交付,它有权将html内容转换为json文件。这意味着json文件需要采用特定的格式,我不知道如何显示它。我还没有制定出如何以所要求的格式格式化nodeChild元素,因此我需要这方面的帮助 这是HTML内容: <body> <style> .myclass{padding-top:50px; left:0;} </style> <div id="maincontent"> &l

我有一个POC要交付,它有权将html内容转换为json文件。这意味着json文件需要采用特定的格式,我不知道如何显示它。我还没有制定出如何以所要求的格式格式化nodeChild元素,因此我需要这方面的帮助

这是HTML内容:

<body>
    <style>
        .myclass{padding-top:50px; left:0;}
    </style>

    <div id="maincontent">
      <div id="myid">
          <p class="myclass">
              This is a paragraph
          </div>
      </div>
</body>

任何帮助都将不胜感激。

这里有一种方法,使用库和:

//别忘了使用`npmi-S节点html解析器`
const HTMLParser=require(“节点html解析器”);
const root=HTMLParser.parse(
`
.myclass{
填充顶部:50px;
左:0;
}
变量名称='世界';
log('Hello'+name);

这是一段

`, { style:true,//保留样式 script:true//保留脚本 } ).查询选择器(“主体”); //清除空白文本节点 root.removeWhitespace(); const result=root.childNodes.reduce((res,node)=>{ //获取最后一个组(`h`、`s`或`j`) const previousGroup=res.slice(-1.pop(); //获取此节点的类型和内容 const{type,propertyName,content}=getProperties(节点); //如果以前的组存在且类型相同 if(previousGroup&&previousGroup.t==类型){ //将内容添加到其中 previousGroup[propertyName]+=内容; }否则{ //否则,创建一个新组 res.push({t:type,[propertyName]:content}); } 返回res; }, []); 函数getProperties(节点){ 开关(节点标记名){ 案例“风格”: 返回{type:“s”,propertyName:“s”,内容:node.rawText.replace(/\s+/g,”)}; 案例“脚本”: 返回{type:“j”,propertyName:“s”,内容:node.rawText}; 违约: 返回{type:“h”,propertyName:“h”,内容:node.innerHTML}; } } 控制台日志(结果); //返回: // [ //{t:'s',s:'.myclass{padding top:50px;left:0;}'}, //{t:'j',s:'var name=\'world\';\n console.log(\'Hello\'+name);'}, //{t:'h',h:'

这是一段

'} // ]
在哪里可以使用没有限制-例如,如果a在该段中,会发生什么情况?我支持上述评论。我不知道您的最终目标是什么,但如果您像这个库那样使用DOM节点及其子节点的实际JSON表示,会不会更容易一些?如果样式在段落内,则将张贴在段落的“h”行内。目前我可以保存一个.json文件,但格式不是预期的,因为子节点都由标记和content.Ok分隔。另外,您是在浏览器中执行此操作,还是在服务器端使用NodeJS执行此操作?这是一个很大的区别。如果它在浏览器中,您可以利用它来遍历DOM,否则,您将需要使用DOM解析库,因为我正在使用NodeJS,映射DOM元素并将其解析为字符串,然后通过一个函数来创建ChildNode和NodeValue列表。目前,我的文件看起来是这样的:{“t”:“DIV”,“content”:[{“t”:“SPAN”,“content”:[“观察它是如何工作的”],“s”:{“class”:“cta_l”}],“s”:{“id”:“cta”,“data bind”:“text:atomk_cta_1.Value”}.--->我需要将所有内容转换为一种类型和内容。@Fernando Fas发布此答案后,我注意到您的示例中没有包含
maincontent
div。因此,您实际上不想要任何顶级节点的outerHTML吗?只需要它们的innerHTML吗?另外,如果有
标记,后跟
de>再说一遍,你想不想把它们分组在一起?嗨,blex,我只需要innerHTML。样式将始终分组在一起,并始终位于顶部,就像你的神奇代码一样,所有div都分组在一起。我注意到解析内容是“const root”的一部分。如果我需要解析指向body标记的外部html文件的内容,该怎么办?@FernandoFas Ok,我对我的答案进行了一些编辑。它现在使用
.querySelector('body'))
以其他HTML中的正文为目标。它使用
innerHTML
而不是
toString
。我注意到库中有一个错误,但是,它在CSS中保留了空白。不过,它是否适合您的需要?嗨,bex,我可以删除CSS中的空白,但是如果您想发布它,我很乐意使用您的解决方案。谢谢。我做到了:)我编辑了上面的答案反映了这些变化
[
{
    "t": "s",
    "s": ".myclass{padding-top:50px; left:0;}"
},
{
    "t": "h",
    "h": "<div id='myid'><p class='myclass'>This is a paragraph</p></div>"
}]
{
            "t": "DIV",
            "content": [{
                "t": "DIV",
                "content": ["This is a paragraph"],
                "s": {
                    "class": "myclass"
                }
            }],
        }
// Don't forget to `npm i -S node-html-parser`
const HTMLParser = require("node-html-parser");

const root = HTMLParser.parse(
  `<!DOCTYPE html>
              <html>
                <head> </head>
                <body>
                  <style>
                    .myclass {
                      padding-top: 50px;
                      left: 0;
                    }
                  </style>

                  <script>
                    var name = 'world';
                    console.log('Hello ' + name);
                  </script>

                  <div id="maincontent">
                    <div id="myid">
                      <p class="myclass">
                        This is a paragraph
                      </p>
                    </div>
                  </div>
                </body>
              </html>`,
  {
    style: true, // Keep styles
    script: true // Keep scripts
  }
).querySelector("body");

// Clean up whitespace text nodes
root.removeWhitespace();

const result = root.childNodes.reduce((res, node) => {
  // Get the last group (`h`, `s` or `j`)
  const previousGroup = res.slice(-1).pop();
  // Get the type and content for this node
  const { type, propertyName, content } = getProperties(node);

  // If previousGroup exists and it's of the same type
  if (previousGroup && previousGroup.t === type) {
    // Add the content to it
    previousGroup[propertyName] += content;
  } else {
    // Otherwise, create a new group
    res.push({ t: type, [propertyName]: content });
  }

  return res;
}, []);

function getProperties(node) {
  switch (node.tagName) {
    case "style":
      return { type: "s", propertyName: "s", content: node.rawText.replace(/\s+/g, " ") };
    case "script":
      return { type: "j", propertyName: "s", content: node.rawText };
    default:
      return { type: "h", propertyName: "h", content: node.innerHTML };
  }
}

console.log(result);
// Returns:
// [
//   { t: 's', s: '.myclass { padding-top: 50px; left: 0; }' },
//   { t: 'j', s: 'var name = \'world\';\n            console.log(\'Hello \' + name);' },
//   { t: 'h', h: '<div id="myid"><p class="myclass">This is a paragraph</p></div>' }
// ]