Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将HTML映射到JSON_Javascript_Html_Json - Fatal编程技术网

Javascript 将HTML映射到JSON

Javascript 将HTML映射到JSON,javascript,html,json,Javascript,Html,Json,我正在尝试将HTML映射为结构完整的JSON。有没有这样的库,或者我需要自己写?我想如果没有html2json库,我可以从xml2json库开始。毕竟,html只是xml的一种变体,对吗 更新:好的,我应该举个例子。我想做的是以下几点。解析html字符串: <div> <span>text</span>Text2 </div> 注意:如果您没有注意到标签,我正在寻找一个Javascript解决方案我在阅读ExtJS时得到了一些链接完整框架本身

我正在尝试将HTML映射为结构完整的JSON。有没有这样的库,或者我需要自己写?我想如果没有html2json库,我可以从xml2json库开始。毕竟,html只是xml的一种变体,对吗

更新:好的,我应该举个例子。我想做的是以下几点。解析html字符串:

<div>
  <span>text</span>Text2
</div>

注意:如果您没有注意到标签,我正在寻找一个Javascript解决方案

我在阅读ExtJS时得到了一些链接完整框架本身就是JSON

联机XML到JSON转换器:

更新 顺便说一句,要获得所添加的JSON,HTML中也需要像这样有类型和内容标记,或者在进行JSON转换时需要使用一些xslt转换来添加这些元素

<?xml version="1.0" encoding="UTF-8" ?>
<type>div</type>
<content>
    <type>span</type>
    <content>Text2</content>
</content>
<content>Text2</content>

div
跨度
文本2
文本2

我刚刚编写了这个函数,它可以满足您的需要;尝试一下,如果不适合您,请告诉我:

// Test with an element.
var initElement = document.getElementsByTagName("html")[0];
var json = mapDOM(initElement, true);
console.log(json);

// Test with a string.
initElement = "<div><span>text</span>Text2</div>";
json = mapDOM(initElement, true);
console.log(json);

function mapDOM(element, json) {
    var treeObject = {};
    
    // If string convert to document Node
    if (typeof element === "string") {
        if (window.DOMParser) {
              parser = new DOMParser();
              docNode = parser.parseFromString(element,"text/xml");
        } else { // Microsoft strikes again
              docNode = new ActiveXObject("Microsoft.XMLDOM");
              docNode.async = false;
              docNode.loadXML(element); 
        } 
        element = docNode.firstChild;
    }
    
    //Recursively loop through DOM elements and assign properties to object
    function treeHTML(element, object) {
        object["type"] = element.nodeName;
        var nodeList = element.childNodes;
        if (nodeList != null) {
            if (nodeList.length) {
                object["content"] = [];
                for (var i = 0; i < nodeList.length; i++) {
                    if (nodeList[i].nodeType == 3) {
                        object["content"].push(nodeList[i].nodeValue);
                    } else {
                        object["content"].push({});
                        treeHTML(nodeList[i], object["content"][object["content"].length -1]);
                    }
                }
            }
        }
        if (element.attributes != null) {
            if (element.attributes.length) {
                object["attributes"] = {};
                for (var i = 0; i < element.attributes.length; i++) {
                    object["attributes"][element.attributes[i].nodeName] = element.attributes[i].nodeValue;
                }
            }
        }
    }
    treeHTML(element, treeObject);
    
    return (json) ? JSON.stringify(treeObject) : treeObject;
}
//使用元素进行测试。
var initElement=document.getElementsByTagName(“html”)[0];
var json=mapDOM(initElement,true);
log(json);
//用字符串测试。
initElement=“text2”;
json=mapDOM(initElement,true);
log(json);
函数mapDOM(元素,json){
var treeObject={};
//如果字符串转换为文档节点
if(元素类型==“字符串”){
if(window.DOMParser){
parser=新的DOMParser();
docNode=parser.parseFromString(元素,“text/xml”);
}否则{//微软又罢工了
docNode=newActiveXObject(“Microsoft.XMLDOM”);
docNode.async=false;
loadXML(元素);
} 
元素=docNode.firstChild;
}
//递归地循环DOM元素并为对象分配属性
函数树HTML(元素、对象){
对象[“类型”]=element.nodeName;
var nodeList=element.childNodes;
if(节点列表!=null){
if(节点列表长度){
对象[“内容”]=[];
对于(变量i=0;i
工作示例:(在Chrome中进行了测试,我不能保证完全支持浏览器-您必须对此进行测试)

​它创建一个对象,该对象包含HTML页面的树结构,格式为您请求的格式,然后使用大多数现代浏览器(IE8+、Firefox 3+等)中包含的
JSON.stringify()
;如果需要支持较旧的浏览器,可以包括

它可以使用DOM元素或包含有效XHTML的
字符串作为参数(我相信,我不确定
DOMParser()
在某些情况下是否会阻塞,因为它设置为
“text/xml”
,或者它只是不提供错误处理。不幸的是
“text/html”
的浏览器支持较差)


通过将不同的值传递为
元素
,可以轻松更改此函数的范围。您传递的任何值都将是JSON映射的根。

表示复杂的HTML文档将很困难,而且充满了各种各样的情况,但我只想与大家分享一些技巧,以展示如何启动此类程序。这个答案的不同之处在于它使用数据抽象和
toJSON
方法递归地构建结果

下面,
html2json
是一个很小的函数,它接受一个HTML节点作为输入,并返回一个JSON字符串作为结果。请特别注意代码是如何非常扁平的,但它仍然能够构建一个深度嵌套的树结构——所有这些几乎都是零复杂性的

//数据元素=元素节点
常数=e=>({
toJSON:()=>({
标记名:
e、 标记名,
文本内容:
e、 文本内容,
属性:
Array.from(e.attributes,({name,value})=>[name,value]),
儿童:
数组.from(e.children,Elem)
})
})
//html2json::节点->JSONString
常量html2json=e=>
stringify(Elem(e),null“”)
console.log(html2json(document.querySelector('main'))

一些标题
一些文本


谢谢你@Gorge Reith。利用@George Reith提供的解决方案,这里有一个函数可以进一步(1)分离单独的“HREF”链接(因为它们可能有用),(2)使用属性作为键(因为属性更具描述性),以及(3)通过使用“jsdom”包,它可以在Node.js中使用,而无需Chrome浏览器:

const jsdom = require('jsdom') // npm install jsdom provides in-built Window.js without needing Chrome


// Function to map HTML DOM attributes to inner text and hrefs
function mapDOM(html_string, json) {
    treeObject = {}

    // IMPT: use jsdom because of in-built Window.js
    // DOMParser() does not provide client-side window for element access if coding in Nodejs
    dom = new jsdom.JSDOM(html_string)
    document = dom.window.document
    element = document.firstChild

    // Recursively loop through DOM elements and assign attributes to inner text object
    // Why attributes instead of elements? 1. attributes more descriptive, 2. usually important and lesser
    function treeHTML(element, object) {
        var nodeList = element.childNodes;
        if (nodeList != null) {
           if (nodeList.length) {
               object[element.nodeName] = []  // IMPT: empty [] array for non-text recursivable elements (see below)
               for (var i = 0; i < nodeList.length; i++) {
                   // if final text
                   if (nodeList[i].nodeType == 3) {
                       if (element.attributes != null) {
                           for (var j = 0; j < element.attributes.length; j++) {
                                if (element.attributes[j].nodeValue !== '' && 
                                    nodeList[i].nodeValue !== '') {
                                    if (element.attributes[j].name === 'href') { // separate href
                                        object[element.attributes[j].name] = element.attributes[j].nodeValue;
                                    } else {
                                        object[element.attributes[j].nodeValue] = nodeList[i].nodeValue;
                                    }

                                }
                           }
                       }
                   // else if non-text then recurse on recursivable elements
                   } else {
                       object[element.nodeName].push({}); // if non-text push {} into empty [] array
                       treeHTML(nodeList[i], object[element.nodeName][object[element.nodeName].length -1]);
                   }
               }
           }
        }
    }
    treeHTML(element, treeObject);

    return (json) ? JSON.stringify(treeObject) : treeObject;
}
const jsdom=require('jsdom')//npm install jsdom提供内置Window.js而不需要Chrome
//函数将HTML DOM属性映射到内部文本和HREF
函数mapDOM(html_字符串,json){
treeObject={}
//IMPT:使用jsdom是因为内置了Window.js
//如果在Nodejs中编码,DOMParser()不提供元素访问的客户端窗口
dom=new jsdom.jsdom(html_字符串)
document=dom.window.document
元素=document.firstChild
const jsdom = require('jsdom') // npm install jsdom provides in-built Window.js without needing Chrome


// Function to map HTML DOM attributes to inner text and hrefs
function mapDOM(html_string, json) {
    treeObject = {}

    // IMPT: use jsdom because of in-built Window.js
    // DOMParser() does not provide client-side window for element access if coding in Nodejs
    dom = new jsdom.JSDOM(html_string)
    document = dom.window.document
    element = document.firstChild

    // Recursively loop through DOM elements and assign attributes to inner text object
    // Why attributes instead of elements? 1. attributes more descriptive, 2. usually important and lesser
    function treeHTML(element, object) {
        var nodeList = element.childNodes;
        if (nodeList != null) {
           if (nodeList.length) {
               object[element.nodeName] = []  // IMPT: empty [] array for non-text recursivable elements (see below)
               for (var i = 0; i < nodeList.length; i++) {
                   // if final text
                   if (nodeList[i].nodeType == 3) {
                       if (element.attributes != null) {
                           for (var j = 0; j < element.attributes.length; j++) {
                                if (element.attributes[j].nodeValue !== '' && 
                                    nodeList[i].nodeValue !== '') {
                                    if (element.attributes[j].name === 'href') { // separate href
                                        object[element.attributes[j].name] = element.attributes[j].nodeValue;
                                    } else {
                                        object[element.attributes[j].nodeValue] = nodeList[i].nodeValue;
                                    }

                                }
                           }
                       }
                   // else if non-text then recurse on recursivable elements
                   } else {
                       object[element.nodeName].push({}); // if non-text push {} into empty [] array
                       treeHTML(nodeList[i], object[element.nodeName][object[element.nodeName].length -1]);
                   }
               }
           }
        }
    }
    treeHTML(element, treeObject);

    return (json) ? JSON.stringify(treeObject) : treeObject;
}
[
   'div',
   {},
   ['span', {}, 'text'],
   'Text2'
]
let element = document.createElement('div')
element.innerHtml = htmlString
/**
 * A NodeDescriptor stands for either an (HTML) Element, or for a text node
 */
export type NodeDescriptor = ElementDescriptor | string

/**
 * Array representing an HTML Element. It consists of:
 *
 * - The (tag) name of the element
 * - An object, mapping attribute keys to attribute values
 * - The (inlined) list of children nodes
 */
export type ElementDescriptor = [
   string,
   Record<string, string>,
   ...NodeDescriptor[]
]

export let htmlToJs = (element: Element, trim = true): ElementDescriptor => {
   let convertElement = (element: Element): ElementDescriptor => {
      let attributeObject: Record<string, string> = {}
      for (let { name, value } of element.attributes) {
         attributeObject[name] = value
      }

      let childArray: NodeDescriptor[] = []
      for (let node of element.childNodes) {
         let converter = htmlToJsDispatch[node.nodeType]
         if (converter) {
            let descriptor = converter(node as any)
            let skip = false

            if (trim && typeof descriptor === 'string') {
               descriptor = descriptor.trim()
               if (descriptor === '') skip = true
            }

            if (!skip) childArray.push(descriptor)
         }
      }

      return [element.tagName.toLowerCase(), attributeObject, ...childArray]
   }

   let htmlToJsDispatch = {
      [element.ELEMENT_NODE]: convertElement,
      [element.TEXT_NODE]: (node: Text): string => node.data,
   }

   return convertElement(element)
}