web-dev-qa-db-ja.com

HTMLをJSONにマップする

構造をそのままにしてHTMLをJSONにマップしようとしています。これを行うライブラリはありますか、または独自に作成する必要がありますか?そこにhtml2jsonライブラリがない場合は、xml2jsonライブラリを開始することができます。結局のところ、htmlはxmlのバリアントにすぎません。

PDATE:さて、おそらく例を挙げるべきでしょう。私がやろうとしていることは次のとおりです。 htmlの文字列を解析します。

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

次のようなjsonオブジェクトに:

{
  "type" : "div",
  "content" : [
    {
      "type" : "span",
      "content" : [
        "Text2"
      ]
    },
    "Text2"
  ]
}

[〜#〜] note [〜#〜]:タグに気付かなかった場合、Javascriptで解決策を探しています

57
nimrod

私はちょうどあなたが望むことをするこの関数を書いたので、それがあなたのために正しく動作しないかどうか私に知らせてください:

_// 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/ (クロームでテスト済み。完全なブラウザーサポートを保証することはできません-これをテストする必要があります)。

リクエストした形式でHTMLページのツリー構造を含むオブジェクトを作成し、ほとんどの最新ブラウザー(IE8 +、Firefox 3+など)に含まれるJSON.stringify()を使用します。古いブラウザをサポートする必要がある場合は、 json2.js を含めることができます。

引数として有効なXHTMLを含む_DOM element_またはstringのいずれかを取ることができます(特定の状況でDOMParser()がそのままチョークするかどうかはわかりません_"text/xml"_に設定するか、単にエラー処理を提供しないかどうか。残念ながら_"text/html"_のブラウザーサポートは不十分です。

別の値をelementとして渡すことにより、この関数の範囲を簡単に変更できます。渡す値はすべて、JSONマップのルートになります。

楽しい

59
George Reith

GitHubのhtml2json&json2html は、John Resigのhtmlparser.jsに基づいて構築されており、いくつかのテストケースが含まれており、私にとってはうまく機能しました。

20
mb21

複雑なHTMLドキュメントを表現することは難しく、隅々までありますが、この種のプログラムを開始する方法を示すために、いくつかのテクニックを共有したかっただけです。この答えは、データ抽象化とtoJSONメソッドを使用して再帰的に結果を構築するという点で異なります

以下のhtml2jsontiny関数で、入力としてHTMLノードを取り、結果としてJSON文字列を返します。コードが非常にフラットであることに特に注意してください。ただし、深くネストされたツリー構造を構築する能力はまだ十分にあります。

// data Elem = Elem Node

const Elem = e => ({
  toJSON : () => ({
    tagName: 
      e.tagName,
    textContent:
      e.textContent,
    attributes:
      Array.from(e.attributes, ({name, value}) => [name, value]),
    children:
      Array.from(e.children, Elem)
  })
})

// html2json :: Node -> JSONString
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に基づいて正しいデータ型を返すことを選択する必要があります。必要

// data Elem = Elem Node | TextElem Node

const TextElem = e => ({
  toJSON: () => ({
    type:
      'TextElem',
    textContent:
      e.textContent
  })
})

const Elem = e => ({
  toJSON : () => ({
    type:
      'Elem',
    tagName: 
      e.tagName,
    attributes:
      Array.from(e.attributes, ({name, value}) => [name, value]),
    children:
      Array.from(e.childNodes, fromNode)
  })
})

// fromNode :: Node -> Elem
const fromNode = e => {
  switch (e.nodeType) {
    case 3:  return TextElem(e)
    default: return Elem(e)
  }
}

// html2json :: Node -> JSONString
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>

とにかく、それは問題に関する2回の繰り返しにすぎません。もちろん、これらの問題が発生した場合に対処する必要がありますが、このアプローチの良い点は、JSONで希望どおりにHTMLをエンコードできる柔軟性が非常に高いことです複雑さを過度に導入しない

私の経験では、この手法を繰り返し使用して、本当に良い結果を得ることができます。この回答が誰にとっても興味深いものであり、私が何かに拡張してほしいなら、私に知らせてください^ _ ^

関連: JavaScriptを使用した再帰メソッド:独自バージョンのJSON.stringifyを構築

8
user633183

これは、JSONからHTMLおよびHTMLからJSONに非常によく似ています https://github.com/andrejewski/himalaya

2
psypersky

ExtJSの完全なフレームワーク自体をJSONで読んでいる間に、私はいつかいくつかのリンクを取得しました。

http://www.thomasfrank.se/xml_to_json.html

http://camel.Apache.org/xmljson.html

オンラインのXMLからJSONへのコンバーター: http://jsontoxml.utilities-online.info/

[〜#〜] update [〜#〜]ところで、問題に追加されたJSONを取得するには、HTMLにもtype&contentタグが必要ですこのようにするか、JSON変換中にこれらの要素を追加するためにxslt変換を使用する必要があります

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

シンプルな HTMLからJSONへのコンバーター があります。 HTMLコードをコピーして貼り付け、ConvertをクリックしてHTMLをJSONに変換できます。

そして、たくさんの Online HTML to JSON Converters があります。

0
Curiousity