JSON과 동등한 XSLT


15

JSON과 동등한 XSLT를 찾거나 필요한 경우 개발하는 데 관심이있었습니다.

내가 찾지 못했을 때 JSON 경로를 일치시키는 데 사용할 수있는 쿼리 언어를 고려하여 일치했을 때 (JavaScript에서) 템플릿을 적용하여 일치하는 패턴 배열을 순서대로 확인하고 첫 번째 템플릿은 xsl : apply-templates와 동일하게하여 템플릿을 자식으로 유지합니다.

JSONPath, JSONQuery 및 RQL을 JSON 쿼리 언어로 알고 있습니다 (RQL이 절대 및 상대 경로를 지원하는지 여부는 명확하지 않지만). 고려해야 할 요소와 그러한 사용법에 대한 각 요소의 상대적인 장점에 대한 제안.


그냥 임의의 생각, JavaScript 및 콧수염 / 핸들 바? :)
Knerd

고마워하지만 표준 접근 방식을 사용하는 데 더 관심이 있습니다 (예 : 일반 JSON 경로 표현식이 라이브러리 고유의 구문과 달리 JSON을 참조하는 일반적으로 인정되는 수단이라는 점에서 잠재적 가능성이있는 방법).
Brett Zamir



Json-> XML-> XSLT-> Json을 수행했습니다. 가장 효율적인 솔루션이 아니더라도 잘 작동합니다.
user2813274

답변:


27

XML : XSLT :: JSON : x . x 란 무엇입니까 ?

가장 쉬운 대답은 x = JavaScript입니다. 당신이 이것을 할 수는 있지만 불만족스러워합니다. XSLT는 기술적으로 Turing complete 이지만 XSLT 의 선언 스타일과 JavaScript에서 볼 수있는보다 명령 적 또는 기능적 스타일 사이에는 대응 성이 좋지 않습니다.

JSONPath , JSONiq , RQL 과 같은 몇 가지 독립형 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으로 작업 할 때 추가 "외국"변환 시스템을 추가하는 대신 모국어로 이러한 작업을 수행하기로 결정한 것은 놀라운 일이 아닙니다.


2
이것은 사려 깊은 대답이므로 +1이지만 여전히 스테핑을 수행하는 라이브러리가있는 선형으로 정렬 된 템플릿을 사용하는 것이 더 깨끗하다고 ​​생각합니다 .XSL에 대한 태도에 대해 옳다고 생각합니다. 캠프가 그것이 형식화 문제라고 생각하지만 재귀 스타일에는 약간의 맞춤화가 필요하다고 생각합니다), 문제의 일부는 그것을 사용하기 위해 그러한 언어를 개발해야 할 때 관성이있을 수 있습니다. JSONPath 자체도 몇 가지 개선이 필요합니다).
Brett Zamir

SpahQL에는 자체 템플릿이없는 것처럼 보이므로 HTML을 JSON /으로 표현할 수있는 라이브러리가 있지만 실제로 데이터 코드와 함께 템플릿 코드에 순수한 JavaScript 또는 JSON을 사용하는 경쟁자가없는 것 같습니다 JS.
Brett Zamir

1
XSLT에 대해서는 복제 할 다른 것이 아무것도 없다는 사실에도 불구하고 +1. JSON은 분명히 쓸만한 내용을 작성하기에 더 어려운 구문이 될 것입니다.
user52889

7

Jonathan은 그의 답변에서 언어로서 XSLT의 본질에 대해 주로 이야기하지만, 고려해야 할 다른 각도가 있다고 생각합니다.

XSLT의 목적은 XML 문서를 다른 문서 (XML, HTML, SGML, PDF 등)로 변환하는 것이 었습니다. 이런 식으로 XSLT는 템플릿 언어로 효과적으로 사용됩니다.

JavaScript 라이브러리로 제한하더라도 광범위한 템플릿 라이브러리가 있습니다 (JSON의 JS는 표기법의 기원만을 참조하므로 JSON을 암시해서는 안되기 때문에 필요하지 않아야 함) JavaScript에만 해당). 이 템플릿 엔진 선택기 는 다양한 JS 옵션을 제공하고 표시합니다.

질문의 후반부에 쿼리 언어에 대한 자세한 내용이 나와 있으며 이러한 언어의 XML 버전은 XPath (XSLT가 아님)입니다. 언급했듯이 다양한 옵션이 있으며 해당 목록에 추가 할 항목이 없습니다. 이 영역은 비교적 새롭기 때문에 하나를 선택하고 함께 진행하는 것이 좋습니다.


의심의 여지가있는 경우, 나는 Jonathan의 대답이 훌륭하다고 생각합니다. 방금 다른 관점을 추가하고 싶었습니다.
Dancrumb

예, 공정 포인트 (예 : XPath는 두 번째 부분과 동일)이지만 JS XSL (JTLT라고 함)이 향상된 JSONPath 변환 JSON을 다른 언어 (예 : HTML과 같은 HTML)로 사용하는 것을보고 싶습니다 문자열 또는 DOM).
Brett Zamir

나는 원시 HTML을 JS / JSON으로 표현하는 것을 선호하는 Jamilih라는 자체 라이브러리를 가지고 있지만 자연스러운 느낌이 필요하며 1) 템플릿 및 경로 일치 2) xsl : apply-templates 및 xsl과 동등한 API 반복을 기대합니다. call-template (xsl : for-each는 JS에는 분명하지만 JSON에는 해당되지 않음) JS의 경우 템플릿 및 JSON (Jamilih 및 반복 API 기반) 기능을 사용할 수 있습니다. Wills ee 어떻게되는지 ...
Brett Zamir

3

다음은 내 (작은 [jslt.min.js] ) JSLT-JavaScript Lightweight Transforms로 수행 할 수있는 작업의 몇 가지 예입니다 .

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

( [jslt.min.js] 무게 ~ 3.1kb 축소 )

즉, 하나의 기능 만

function Per ( subject ) { ... }

... 실제로 XSLT (1.0)의 처리 모델을 모방 합니다 .

(참조, Per의 신체에서 "변형"과 "템플릿"내부 기능)

본질적으로, 그것은 단지 하나의 모든 것에서 구워졌습니다 function Per ( subject ) { ... }.

1) 배열 주제

노드 집합 생성 / 필터링 / 평탄화 / 그룹 / 정렬 / 등 , 피사체가 생성 노드 집합 (AN 배열이면 배열 뿐만 아니라)를 통해 확장하고, 따라서라는 메소드 (에 바인딩 만을 반환 배열 호출의 인스턴스 Per ( subjectArray )되고 확장, 즉 Array.prototype은 그대로 유지됩니다)

즉, Per :: 배열 --> 배열

( groupBy, orderBy, flattenBy 등과 같은 자체 설명 이름을 갖는 결과 Array 의 확장 메소드-예제의 사용법 참조)

2) 문자열 주제

subject가 문자열 인 경우 문자열 보간

( "Per" map ( source )은 제목 템플릿 문자열에 바인딩 된 메소드를 가진 객체를 반환 합니다)

즉, 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)" }

동안 (많은 모두 <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
꽤 괜찮은데.
Robert Harvey

@RobertHarvey : 섹션 5.1 의 간결함 외에도 오래 전에 알았던 것 자체는 결국 에반 렌츠 (Evan Lenz)의 "XSLT는 생각보다 단순하다!"라는 흥미를 불러 일으켰다 . lenzconsulting.com/how-xslt-works- 그래서 저는 JavaScript 인 매우 가단성있는 언어로 그 주장 (호기심이있는 경우에만)을 검증하기로 결정했습니다.
YSharp

자세한 답변에 감사드립니다. 나는 다른 것들 (나 자신의 XSLT에 상응하는 것을 포함하여)로 바쁘지만 더 신중하게 살펴보기 위해 이것으로 돌아갈 생각입니다.
Brett Zamir

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 }
  ]
}

이 변환은 세 가지 규칙으로 구성됩니다. 첫 번째는 Honda가 만든 모든 자동차와 일치하여 Honda속성을 가진 객체를 방출 한 다음 재귀 적으로 일치시킵니다. 두 번째 규칙은 객체와 maker속성을 일치 시켜 modelyear속성을 출력합니다 . 마지막은 재귀 적으로 일치하는 항등 변환입니다.


정보에 대한 +1 및 감사합니다. 어느 시점에서 내 자신의 github.com/brettz9/jtlt를 완성 하기를 희망 하지만 비교할 더 많은 구현이 도움이됩니다.
Brett Zamir

-1

나는 당신이 JSON 그 자체로 JSON 변형을 얻지 못할 것이라고 생각합니다. Python의 Jinja2, JavaScripts Nunjucks, Groovy MarkupTemplateEngine 등 원하는 템플릿 엔진과 여러 가지 템플릿 엔진이 있습니다. .NET에는 T4 및 JSON 직렬화 / 직렬화 지원 기능이 있으므로 그 기능도 있습니다.

직렬화 된 JSON 데이터는 기본적으로 사전 또는 맵 구조이므로 템플릿 엔진을 지나서 원하는 노드를 반복합니다. 그런 다음 JSON 데이터가 템플릿에 의해 변환됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.