JSONに相当するXSLT


14

JSONに相当するXSLTを見つける(または必要に応じて開発する)ことに興味がありました。

私は何も見つけていないので、一致したときにテンプレートを(JavaScriptから)適用するためにJSONパスの一致に使用できるクエリ言語を考えていました(おそらく一致するパターンの配列を順番にチェックし、一致する最初のテンプレート。ただし、xsl:apply-templatesに相当するものを許可し、テンプレートを子供向けに保持します)。

JSONPath、JSONQuery、RQLをJSONクエリ言語として認識しています(ただし、RQLが絶対パスと相対パスをサポートしているかどうかは明確ではありませんでした)。考慮すべき要素に関する提案と、そのような使用法に対するそれぞれの相対的な利点。


JavaScriptとMoustache / Handlebarsをランダムに考えただけですか?:)
Knerd

感謝しますが、私は標準的なアプローチを使用することにもっと熱心です(たとえば、一般的なJSONパス式は、ライブラリに固有の構文とは対照的に、JSONを参照する一般的に認識される手段であることを考えれば、少なくとも1つの可能性があります)。
ブレットザミール14



私が行っているJSON - > XML - > XSLT - > JSON前に-それは、それが最も効率的な解決策ではないのです場合でも、罰金を作品
user2813274は

回答:


27

XML:XSLT :: JSON:Xxとは何ですか?

最も簡単な答えはx = JavaScriptです。これについて主張することはできますが、それは不満を感じます。XSLTは技術的にはチューリング完全ですが、XSLT の宣言型スタイルとJavaScriptで見られるより命令的または機能的なスタイルとの間には、対応が不十分です。

JSONPathJSONiqRQLのようないくつかのスタンドアロンJSONクエリ言語があります。これらは、XML:XPath :: JSON:y(または、XPathではなくXQuery)の中間的な立場を表しています。また、すべてのJSONに焦点を当てたドキュメントデータベースには、JSON関連のクエリ言語があります。

しかし現実には、SpahQLのような完全なXSLTの位置に対していくつかの競争相手がいるにもかかわらず、一般的に受け入れられ、広くサポートされているXSLTに相当するJSONはありません。

どうして?

世界中のすべてのJSONで、なぜXSLTに(より直接的な)アナログがないのですか?多くの開発者がXSLTを失敗した実験と見なしているためです。どの検索エンジンでも、「XSLTは痛みに包まれた失敗です」などの引用につながります。他の人たちは、それがもっと良くフォーマットされていればもっと人気があると主張しました。しかし、XSLTへの関心は一般的に長年にわたって低下しています。それをサポートする多くのツールは、1999仕様であるバージョン1.0のみをサポートします。15年前のスペック?より新しい2.0仕様があり、人々がXSLTに熱心であれば、サポートされます。そうではありません。

概して、大規模な開発者は、変換テンプレートではなくコードを使用してXMLドキュメントを処理および変換することを選択しています。したがって、JSONを使用する場合、追加の「外国の」変換システムを追加するのではなく、JSONを母国語で選択することは当然のことです。


2
これは思慮深い返信であるため+1ですが、ライブラリをステップ実行する直線的なテンプレートの束を持っている方がきれいだと思いますが、XSLに対する態度についてはおそらく正しいと思います(私は再帰的なスタイルには確かにある程度のカスタマイズが必要ですが、フォーマットの問題だと考えてキャンプに寄りかかってください)、それを使用するためにそのような言語を開発する必要があるため、慣性のいくつかの問題があるのではないかと思いますJSONPath自体にもいくつかの機能強化が必要です)。
ブレットザミール14

SpahQLには独自のテンプレートがないように思われたため、HTMLをJSON /として表現できるライブラリが存在する場合でも、テンプレートコードに(データ構造とともに)純粋なJavaScriptまたはJSONを実際に使用する競合他社はまだないようです。 JS
ブレットザミール14

1
XSLTについては、何も複製できないものがあるという事実にもかかわらず、+ 1。JSONは確かに、使用可能な同等のコードを記述するのが難しい構文になります。
user52889

7

ジョナサンは主にXSLTの言語としての性質について彼の答えで語っていますが、考慮すべき別の角度があると思います。

XSLTの目的は、XMLドキュメントを他のドキュメント(XML、HTML、SGML、PDFなど)に変換することでした。このように、XSLTはテンプレート言語として効果的に頻繁に使用されます。

JSONのJSは表記法の起源を参照するだけであり、そのJSONを暗示するものではないため、JavaScriptライブラリに制限する場合でも、膨大なテンプレートライブラリがあります(これは必要ありません) JavaScript専用です)。このテンプレートエンジンセレクタは、そこにあるさまざまなJSオプションを提供し、表示します。

質問の後半では、クエリ言語について詳しく説明します。これらのXMLバージョンはXPath(XSLTではありません)です。ご指摘のとおり、そこにはさまざまなオプションがあり、そのリストに追加するものは何もありません。この領域は比較的新しいため、いずれかを選択してそのまま使用することをお勧めします。


疑問がある場合は、ジョナサンの答えは素晴らしいと思います。別の観点を追加したかっただけです。
ダンクラム14

はい、公正な点(そして、2番目の部分と同等のXPathです)が、JS XSL(JTLTと呼ばれる)が拡張JSONPath変換JSONを別の言語(つまり、HTMLとして文字列またはDOM)。
ブレットザミール14

私はJamilihと呼ばれる独自のライブラリを持っています。これは生のHTMLをJS / JSONとして表現するのに適していますが、1)テンプレートとパスマッチング2)xsl:apply-templatesとxslに相当するAPIを反復するためにキャッチーなことを望みます: call-template(xsl:for-eachはJSでは明らかですが、JSONではわかりません)。JSの場合、テンプレート用の関数とJSON(Jamilihおよび反復APIに基づく)用の関数を使用できます。ウィルズは、それは...どのようになるEE
ブレットザミール

3

ここに、私の(small [jslt.min.js])JSLT-JavaScript Lightweight Transformsでできることの例をいくつか示します。

https://jsfiddle.net/YSharpLanguage/c7usrpsL/10

[jslt.min.js]の重量は〜3.1kb縮小されます

つまり、ただ1つの関数、

function Per ( subject ) { ... }

...これは実際にXSLT(1.0)の処理モデルを模倣しています

(Perの本文の「変換」および「テンプレート」内部関数を参照)

そのため、本質的には、その単一のすべてに単純に焼き付けられfunction Per ( subject ) { ... }、その一意の引数のタイプの評価をフォークして、以下のいずれかを実装します。

1)配列サブジェクト

ノードセットの作成/フィルタリング/平坦化/グループ/順序/など、被験者は、得られるノード集合(配列である場合、配列同様)を(で拡張し、それに応じて名前のメソッドにバインドされているだけ戻さアレイへのコールのインスタンスPer ( subjectArray )IS拡張;つまり、Array.prototypeは変更されません)

すなわち、Per :: Array --> Array

(groupBy、orderBy、flattenByなどのわかりやすい名前を持つArrayの拡張メソッド-例の使用法を参照)

2)ストリング件名

件名が文字列の場合、文字列補間

(「Per」はmap ( source )、サブジェクトテンプレート文字列にバインドされたmethodを持つオブジェクトを返します)

すなわち、Per :: String --> {map : :(AnyValue --> String)}

例えば、

Per("Hi honey, my name is {last}. {first}, {last}.").map({ "first": "James", "last": "Bond" })

収量:

"Hi honey, my name is Bond. James, Bond."

どちらかの

Per("Those '{*}' are our 10 digits.").map([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ])

または

Per("Those '{*}' are our 10 digits.").map(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

同じ結果が得られます。

"Those '0123456789' are our 10 digits."

だけ

Per("Those '{*}' are our 10 digits.").map([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], ", ")

利回り

"Those '0, 1, 2, 3, 4, 5, 6, 7, 8, 9' are our 10 digits."

3)サブジェクトの変換

XSLTの類似変換。サブジェクトが、従来のように定義された書き換え規則の配列を提供する「$」メンバーを持つハッシュである場合(および(2)と同じ)、「Per」はmap ( source )、サブジェクトにバインドされたメソッドを持つオブジェクトを返します変換-どこ

「ruleName」Per ( subjectTransform [ , ruleName ])はオプションであり、<xsl:call-template name = "templateName"> ...と同様の機能を提供します。

すなわち、Per : :(Transform [、ruleName :: String ])-->{map : :( --> AnyValue AnyValue)}

変換 :: {$ :: 書き換えルールの配列[rw.r.] }

[rw.r.]述語とテンプレート関数のペア)

例えば、与えられた(...他の不自然な例)

// (A "Member" must have first and last names, and a gender)
function Member(obj) {
  return obj.first && obj.last && obj.sex;
}

var a_transform = { $: [
//...
  [ [ Member ], // (alike <xsl:template match="...">...)
      function(member) {
        return {
          li: Per("{first} {last}").map(member) +
              " " +
              Per(this).map({ gender: member.sex })
        };
      }
  ],

  [ [ function(info) { return info.gender; } ], // (alike <xsl:template match="...">...)
      function(info) { return Per("(gender: {gender})").map(info); }
  ],

  [ [ "betterGenderString" ], // (alike <xsl:template name="betterGenderString">...)
      function(info) {
        info.pronoun = info.pronoun || "his/her";
        return Per("({pronoun} gender is {gender})").map(info);
      }
  ]
//...
] };

それから

Per(a_transform).map({ "first": "John", "last": "Smith", "sex": "Male" })

収量:

{ "li": "John Smith (gender: Male)" }

while ...(ほとんど同じ<xsl:call-template name="betterGenderString">...

"James Bond... " +
Per(a_transform, "betterGenderString").map({ "pronoun": "his", "gender": "Male" })

収量:

"James Bond... (his gender is Male)"

そして

"Someone... " +
Per(a_transform, "betterGenderString").map({ "gender": "Male or Female" })

収量:

"Someone... (his/her gender is Male or Female)"

4)そうでなければ

アイデンティティ関数、他のすべての場合

すなわち、Per :: T --> T

(すなわちPer === function ( value ) { return value ; }

注意

上記の(3)で、テンプレート関数の本文にあるJavaScriptの「this」は、コンテナー/所有者変換とそのルールセット($:[...]配列で定義されている)にバインドされているため、そのコンテキストで、式「Per(this)」をXSLTと同等の機能的に近いものにする

<xsl:apply-templates select="..."/>

'HTH、


1
それはいいね。
ロバートハーベイ

@RobertHarvey:セクション5.1の簡潔さと、私がずっと前に気づいていたそれ自体に加えて、エヴァンレンツの「XSLTはあなたが思っているよりも簡単です!」というhttp:// wwwで興味をそそられ、インスピレーションを得ました。 lenzconsulting.com/how-xslt-works-そのため、非常に順応性のあるJavaScriptの言語で、その主張(好奇心からのみ)を検証することに挑戦することにしました。
YSharp

詳細な返信ありがとうございます。私は他にもいくつかのことで忙しいのですが(私自身のXSLTの同等物を含む)、私はこれに戻ってもっと注意深く見てみたいと思います。
ブレットザミール

3

私は最近、まさにこの目的のためにライブラリjson-transformsを作成しました。

https://github.com/ColinEberhardt/json-transforms

XPathにモデル化されたDSL であるJSPathと、XSLTに直接触発された再帰的パターンマッチングアプローチの組み合わせを使用します。

以下に簡単な例を示します。次のJSONオブジェクトがある場合:

const json = {
  "automobiles": [
    { "maker": "Nissan", "model": "Teana", "year": 2011 },
    { "maker": "Honda", "model": "Jazz", "year": 2010 },
    { "maker": "Honda", "model": "Civic", "year": 2007 },
    { "maker": "Toyota", "model": "Yaris", "year": 2008 },
    { "maker": "Honda", "model": "Accord", "year": 2011 }
  ]
};

変換は次のとおりです。

const jsont = require('json-transforms');
const rules = [
  jsont.pathRule(
    '.automobiles{.maker === "Honda"}', d => ({
      Honda: d.runner()
    })
  ),
  jsont.pathRule(
    '.{.maker}', d => ({
      model: d.match.model,
      year: d.match.year
    })
  ),
  jsont.identity
];

const transformed  = jsont.transform(json, rules);

次の出力:

{
  "Honda": [
    { "model": "Jazz", "year": 2010 },
    { "model": "Civic", "year": 2007 },
    { "model": "Accord", "year": 2011 }
  ]
}

この変換は、3つのルールで構成されています。最初のものは、ホンダによって作られた自動車にマッチし、Hondaプロパティを持つオブジェクトを放出してから、再帰的にマッチします。二番目のルールは、で任意のオブジェクトに一致するmaker出力、プロパティmodelおよびyearプロパティを。最後は、再帰的に一致するID変換です。


+1と情報をありがとう。ある時点で自分のgithub.com/brettz9/jtltを完成させることを望んでいますが、比較する実装を増やしておくと役に立ちます。
ブレットザミール

-1

JSON自体のJSONバリアントを取得することはないと思います。PythonのJinja2、JavaScripts Nunjucks、Groovy MarkupTemplateEngineなど、いくつかのテンプレートエンジンが存在します。.NETにはT4およびJSONのシリアル化/逆シリアル化のサポートがあるため、それも可能です。

直列化されたJSONデータは基本的に辞書またはマップ構造であるため、テンプレートエンジンを通過し、そこで目的のノードを反復処理します。次に、JSONデータはテンプレートによって変換されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.