HTML을 JSON에 매핑
HTML을 구조 그대로 JSON에 매핑하려고 합니다.이 기능을 제공하는 도서관이 있나요? 아니면 제가 직접 써야 하나요?html2json 라이브러리가 없는 경우 xml2json 라이브러리를 사용할 수 있습니다.어쨌든 html은 xml의 변형일 뿐입니다.
업데이트: 예를 들어 보겠습니다.제가 하려는 것은 다음과 같습니다.html 문자열을 구문 분석합니다.
<div>
<span>text</span>Text2
</div>
다음과 같은 json 객체로 변환합니다.
{
"type" : "div",
"content" : [
{
"type" : "span",
"content" : [
"Text2"
]
},
"Text2"
]
}
주의: 태그를 눈치채지 못한 경우 Javascript에서 해결책을 찾고 있습니다.
이 기능은 고객이 원하는 대로 작성했습니다.실행해 보고, 문제가 있는 경우는 알려 주세요.
// 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;
}
작업 예: http://jsfiddle.net/JUSsf/ (Chrome에서 테스트 완료, 완전한 브라우저 지원은 보증할 수 없습니다.이것을 테스트해 주세요.)
구조를 HTML을합니다.JSON.stringify()
최신 브라우저(IE8+, Firefox 3+ 등)에 포함되어 있습니다.구식 브라우저를 지원하려면 json2.js를 포함할 수 있습니다.
DOM 요소 중 할 수 .string
XHTML」이 「XHTML」(「XHTML」, 「XHTML」)하고 있는지 하지 않습니다).DOMParser()
상황에서 in will 、 、 、 、 will will will will will will will will will로 되어 있기 합니다."text/xml"
에러 처리를 하지 않는지도 모릅니다.도 ★★★★★★★★★★★★★★★."text/html"
의
를 쉽게 수 .element
JSON을 사용하다
htlm2json
복잡한 HTML 문서를 표현하는 것은 어렵고, 코너 케이스로 가득합니다만, 이러한 종류의 프로그램을 시작하는 방법을 보여 주는 몇 가지 기술을 공유하고 싶습니다. 추상화를 .toJSON
를
래,,html2json
는 HTML 노드를 입력으로 사용하고 그 결과 JSON 문자열을 반환하는 작은 함수입니다.특히 코드가 매우 평평하지만 여전히 깊이 중첩된 트리 구조를 구축할 수 있는 충분한 기능을 갖추고 있어 복잡성이 거의 없는 것이 가능합니다.
const Elem = e => ({
tagName:
e.tagName,
textContent:
e.textContent,
attributes:
Array.from(e.attributes, ({name, value}) => [name, value]),
children:
Array.from(e.children, Elem)
})
const html2json = e =>
JSON.stringify(Elem(e), null, ' ')
console.log(html2json(document.querySelector('main')))
<main>
<h1 class="mainHeading">Some heading</h1>
<ul id="menu">
<li><a href="/a">a</a></li>
<li><a href="/b">b</a></li>
<li><a href="/c">c</a></li>
</ul>
<p>some text</p>
</main>
예에서는 " " " 입니다.textContent
간간도도도도도도 또 데이터 즉 데이터 생성자를 합니다.TextElem
childNodes
)children
를 에 하도록 선택합니다.e.nodeType
– 이를 통해 필요한 것에 조금 더 다가갈 수 있습니다.
const TextElem = e => ({
type:
'TextElem',
textContent:
e.textContent
})
const Elem = e => ({
type:
'Elem',
tagName:
e.tagName,
attributes:
Array.from(e.attributes, ({name, value}) => [name, value]),
children:
Array.from(e.childNodes, fromNode)
})
const fromNode = e => {
switch (e?.nodeType) {
case 1: return Elem(e)
case 3: return TextElem(e)
default: throw Error(`unsupported nodeType: ${e.nodeType}`)
}
}
const html2json = e =>
JSON.stringify(Elem(e), null, ' ')
console.log(html2json(document.querySelector('main')))
<main>
<h1 class="mainHeading">Some heading</h1>
<ul id="menu">
<li><a href="/a">a</a></li>
<li><a href="/b">b</a></li>
<li><a href="/c">c</a></li>
</ul>
<p>some text</p>
</main>
어쨌든, 그 문제에 대한 두 번의 반복입니다.물론 각 케이스에 대응해야 합니다만, 이 어프로치의 장점은 HTML을 JSON에서 원하는 대로 인코딩할 수 있는 유연성이 매우 뛰어나고, 복잡함도 크지 않다는 것입니다.
제 경험상 이 기술을 계속 반복하면 정말 좋은 결과를 얻을 수 있습니다.이 답변에 흥미가 있는 분이 계시다면 자세히 설명해 주세요^_^
관련:JavaScript를 사용한 재귀 메서드: JSON.stringify 자체 버전 구축
json2의 출력
위에서는 HTML에서 JSON으로 넘어갔고, 이제 JSON에서 HTML로 넘어갈 수 있게 되었습니다.데이터를 잃지 않고 두 가지 데이터 유형을 변환할 수 있는 것을 동형이라고 합니다.여기서 기본적으로 하고 있는 것은 위의 각 함수의 역수를 쓰는 것입니다.
const HtmlNode = (tagName, attributes = [], children = []) => {
const e = document.createElement(tagName)
for (const [k, v] of attributes) e.setAttribute(k, v)
for (const child of children) e.appendChild(toNode(child))
return e
}
const TextNode = (text) => {
return document.createTextNode(text)
}
const toNode = t => {
switch (t?.type) {
case "Elem": return HtmlNode(t.tagName, t.attributes, t.children)
case "TextElem": return TextNode(t.textContent)
default: throw Error("unsupported type: " + t.type)
}
}
const json2html = json =>
toNode(JSON.parse(json))
const parsedJson =
{"type":"Elem","tagName":"MAIN","attributes":[],"children":[{"type":"TextElem","textContent":"\n "},{"type":"Elem","tagName":"H1","attributes":[["class","mainHeading"]],"children":[{"type":"TextElem","textContent":"Some heading"}]},{"type":"TextElem","textContent":"\n "},{"type":"Elem","tagName":"UL","attributes":[["id","menu"]],"children":[{"type":"TextElem","textContent":"\n "},{"type":"Elem","tagName":"LI","attributes":[],"children":[{"type":"Elem","tagName":"A","attributes":[["href","/a"]],"children":[{"type":"TextElem","textContent":"a"}]}]},{"type":"TextElem","textContent":"\n "},{"type":"Elem","tagName":"LI","attributes":[],"children":[{"type":"Elem","tagName":"A","attributes":[["href","/b"]],"children":[{"type":"TextElem","textContent":"b"}]}]},{"type":"TextElem","textContent":"\n "},{"type":"Elem","tagName":"LI","attributes":[],"children":[{"type":"Elem","tagName":"A","attributes":[["href","/c"]],"children":[{"type":"TextElem","textContent":"c"}]}]},{"type":"TextElem","textContent":"\n "}]},{"type":"TextElem","textContent":"\n "},{"type":"Elem","tagName":"P","attributes":[],"children":[{"type":"TextElem","textContent":"some text"}]},{"type":"TextElem","textContent":"\n"}]}
document.body.appendChild(toNode(parsedJson))
예전에 ExtJs의 풀 프레임워크 자체가 JSON이라는 것을 읽었을 때 링크를 거의 받지 못했습니다.
http://www.thomasfrank.se/xml_to_json.html
http://camel.apache.org/xmljson.html
온라인 XML-JSON 변환기:http://jsontoxml.utilities-online.info/
업데이트 BTW, 문제가 된 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>
HTML을 다음과 같이 JSON으로 표현해야 하는 유사한 문제가 있었습니다.
- HTML 을 합니다.
string
- HTML 요소의 경우 다음 배열을 사용합니다.
- 요소의 (태그) 이름
- 객체, 속성 키에 속성 값 매핑
- 하위 노드의 (인된) 목록
예:
<div>
<span>text</span>Text2
</div>
된다
[
'div',
{},
['span', {}, 'text'],
'Text2'
]
DOM Element를 이러한 JS 구조로 변환하는 기능을 작성했습니다.이 기능은 이 답변의 끝에 있습니다.함수는 Typescript에 기재되어 있습니다.타입스크립트 플레이그라운드를 사용하여 클린 JavaScript로 변환할 수 있습니다.
게다가 html 문자열을 DOM 에 해석할 필요가 있는 경우는, 에 할당합니다..innerHtml
:
let element = document.createElement('div')
element.innerHtml = htmlString
또, 이것은 일반적인 지식입니다만, JSON 문자열의 출력이 필요한 경우는, 을 사용해 주세요.
/**
* 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)
}
@Gorge Reith 감사합니다.@George Reith가 제공한 솔루션을 바탕으로 (1) 각각의 'hrefs' 링크를 더욱 분리하는 기능, (2) 속성을 키로 사용하는 기능(속성이 더 설명적이기 때문에), (3) Chrome을 사용하지 않고 Node.j 내에서 사용할 수 있는 기능.
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;
}
언급URL : https://stackoverflow.com/questions/12980648/map-html-to-json
'programing' 카테고리의 다른 글
PHP 네임스페이스 5.3 및 WordPress 위젯 (0) | 2023.03.18 |
---|---|
Wordpress에서 현재 게시 ID를 사용하여 다음/이전 게시 ID 가져오기 (0) | 2023.03.18 |
spring-boot-configuration-processor란 무엇입니까?왜 사람들은 도서관에서 도서관을 제외할까?의존관계 트리에서는 왜 보이지 않는가? (0) | 2023.03.18 |
스프링 부트 application.properties에서 신뢰 저장소 정보 지정 (0) | 2023.03.18 |
JPA 및 휴지 상태를 사용하여 MySQL JSON 열을 Java 엔티티 속성에 매핑하는 방법 (0) | 2023.03.18 |