JSON için XSLT eşdeğeri


15

JSON için bir XSLT eşdeğeri bulmakla (veya gerekirse geliştirmekle) ilgileniyordum.

Ben hiç bulamadım gibi, bir maç (muhtemelen sadece eşleşen desen bir dizi kontrol ve durdurma) sırasında şablonlar (JavaScript) uygulamak için JSON yolları eşleştirmek için kullanmak için olası sorgu dili düşünüyordum eşleşen ilk şablon, ancak eşdeğer xsl: uygulamak-şablonlar şablonlar çocuklar için devam tutmak için izin).

JSONPath, JSONQuery ve RQL JSON sorgu dilleri olarak farkındayım (RQL mutlak ve göreli yolları destekleyip desteklemediği konusunda tam olarak açık olmasam da). Dikkate alınması gereken faktörler ve her birinin böyle bir kullanıma yönelik göreceli avantajları hakkında herhangi bir öneri.


Sadece rastgele bir düşünce, JavaScript ve Bıyık / Gidon belki? :)
Knerd

Teşekkürler, ancak standart bir yaklaşım kullanmaya daha hevesliyim.
Brett Zamir



Daha önce Json -> XML -> XSLT -> Json yaptım - en verimli çözüm olmasa bile, iyi çalışıyor,
user2813274 5:14

Yanıtlar:


27

XML: XSLT :: JSON: x . Nedir x ?

En kolay cevap x = JavaScript olacaktır. Bunun için bir dava açabilseniz de tatmin edici değil. XSLT teknik olarak Tamamlanmış olsa da, XSLT'nin bildirimsel stili ile JavaScript'te görülen daha zorunlu veya işlevsel stiller arasında zayıf bir yazışma vardır .

XML: XPath :: JSON: y (veya muhtemelen XPath yerine XQuery) için geçerli olabilecek JSONPath , JSONiq ve RQL gibi birkaç bağımsız JSON sorgu dili vardır . Ve her JSON odaklı belge veritabanında JSON ile ilgili bir sorgu dili vardır .

Ancak gerçek şu ki, SpahQL gibi tam XSLT pozisyonu için birkaç yarışmacı olmasına rağmen, XSLT'ye genel olarak kabul edilmiş, geniş çapta desteklenen JSON eşdeğeri yoktur.

Neden?

Dünyadaki bütün JSON ile neden değil XSLT bir (daha doğrudan) analog var? Çünkü birçok geliştirici XSLT'yi başarısız bir deneme olarak görüyor. Herhangi bir arama motoru "XSLT acı sarılmış bir başarısızlıktır" gibi tırnak işaretleri yol açacaktır. Diğerleri, daha iyi biçimlendirilmiş olsaydı, daha popüler olacağını savundu. Ancak XSLT'ye olan ilgi genellikle yıllar içinde azaldı . Bunu destekleyen birçok araç, 1999 belirtimi olan yalnızca 1.0 sürümünü destekler . Onbeş yaşındaki teknik özellikler? Çok daha yeni bir 2.0 spesifikasyonu var ve eğer insanlar XSLT konusunda hevesli olsaydı, desteklenecekti. Öyle değil.

Büyük geliştiriciler dönüşüm belgelerini değil XML belgelerini kodla işlemeyi ve dönüştürmeyi seçtiler. Bu nedenle, JSON ile çalışırken, ek bir "yabancı" dönüşüm sistemi eklemek yerine, genel olarak bunu kendi dillerinde yapmayı seçmeleri şaşırtıcı değildir.


2
Bu düşünceli bir cevap olarak +1, ancak yine de adım adım ilerleyen bir kütüphane ile doğrusal olarak düzenlenmiş şablonların bir demetinin daha temiz olduğunu düşünüyorum ve sanırım XSL'ye karşı tutum konusunda haklı olduğunuzu düşünürken (I kampa yaslanın, özyinelemeli tarzın kuşkusuz bazı alıştırmalara ihtiyaç duymasına rağmen bir biçimlendirme sorunu olduğunu düşünüyoruz), bahse girerim, sorunun bir kısmını kullanmak için böyle bir dil geliştirmeye ihtiyaç duymakta atalet olabilir (örneğin, buluyorum JSONPath'ın bile birkaç geliştirmeye ihtiyacı vardır).
Brett Zamir

SpahQL'in kendi şablonları yok gibi görünmüyor, bu yüzden HTML kodunun JSON / JS.
Brett Zamir

1
XSLT hakkında başka hiçbir şeyin çoğaltmayı başaramadığı bir şey olmasına rağmen +1. JSON kesinlikle kullanılabilir bir eşdeğer yazmak için daha zor bir sözdizimi olacak.
user52889

7

Jonathan, cevabında bir dil olarak XSLT'nin doğasından büyük ölçüde söz ederken, düşünülmesi gereken başka bir açı olduğunu düşünüyorum.

XSLT'nin amacı XML belgelerini başka bir belgeye (XML, HTML, SGML, PDF vb.) Dönüştürmekti. Bu yolla, XSLT sıklıkla bir şablon dili olarak etkin bir şekilde kullanılır.

Kendinizi JavaScript kitaplıklarıyla sınırlasanız bile çok sayıda şablon kitaplığı vardır (buna gerek yoktur, çünkü JSON'daki JS yalnızca gösterimin oluşumunu ifade eder ve bu JSON'u ima etmek için alınmamalıdır. yalnızca JavaScript içindir). Bu şablon motoru seçici orada JS seçenekleri çeşitli verir ve gösterir.

Sorularınızın ikinci yarısı sorgu dilleri hakkında daha fazla konuşuyor ve bunların XML sürümü XPath (XSLT değil) olacaktır. Belirttiğiniz gibi, orada çeşitli seçenekler var ve bu listeye eklenecek hiçbir şey yok. Bu alan nispeten yeni, bu yüzden birini seçip sadece onunla gitmenizi öneririm.


Herhangi bir şüphe olması durumunda, bence Jonathan'ın cevabı harika; Sadece alternatif bir bakış açısı eklemek istedim.
Dancrumb

Evet, adil noktalar (ve evet re: XPath ikinci bölüm için eşdeğerdir), ancak JS XSL'imin (JTLT olarak adlandırılır) gelişmiş bir JSONPath dönüşümü JSON'u başka bir dile dönüştürdüğünü görmekle ilgileniyorum (ör. dize veya DOM).
Brett Zamir

Ben Jamilih adlı kendi kitaplığım var ben JS / JSON olarak ham HTML ifade etmek için tercih, ama doğal bir şey hissediyorum ve ben 1 için çekici ve umarım 1) Şablonlar ve yol eşleştirme 2) xsl eşdeğer yineleme API'ları: uygulama-şablonları ve xsl: call-template (xsl: for-each JS için açıktır, ancak JSON için açık değildir). JS için, şablonlar ve JSON (Jamilih ve bu yineleme API'larına dayalı) işlevlerini kullanabilirim. Wills ee nasıl gidiyor ...
Brett Zamir

3

İşte benim (small [jslt.min.js] ) JSLT ile yapabileceklerinize birkaç örnek : JavaScript Hafif Dönüşümler:

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

( [jslt.min.js] ~ 3,1 kb küçültülmüş )

yani sadece bir işlev,

function Per ( subject ) { ... }

... aslında XSLT (1.0) 'ın işleme modelini taklit ediyor .

(bkz. Per'in gövdesinde "dönüştürme" ve "şablon" iç fonksiyonları)

Yani, özünde, basitçe, hepsi function Per ( subject ) { ... }de (aynı zamanda) benzersiz argümanının türüne ilişkin değerlendirmesini çağıran, o ikisine de pişirilir :

1) Dizi konusu

nodeset oluşturma / süzme / düzleşme / gruplama / sipariş / vs. , söz konusu elde edilen nodeset (örneğin, bir dizi, eğer Dizi sıra) ile uzatılabilir ve buna göre adlandırılır yöntemler (bağlı olduğu sadece geri Dizi çağrısı örneği Per ( subjectArray )IS genişletilmiş; yani, Array.prototype dokunulmaz)

yani, Per :: Dizi --> Dizi

(Elde Array - örneklerde kullanım karşılaştırınız uzantısıdır yöntemleri, vb GroupBy, orderBy, flattenBy, hem kendini açıklayan adları olan)

2) Dize konusu

Konu bir dize ise dize enterpolasyonu

("Per" daha sonra map ( source ), konu şablon dizesine bağlı bir yöntemle bir nesne döndürür )

yani, Per :: String --> {map :: ( AnyValue --> String )}

Örneğin,

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

verim:

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

ikisinden biri

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

veya

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

aynı verir:

"Those '0123456789' are our 10 digits."

ama yalnızca

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

verim

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

3) Konuyu dönüştür

XSLT benzeri dönüşüm , eğer özne, yeniden yazma kuralları dizisini sağlayan geleneksel olarak tanımlanmış bir "$" üyesi olan bir karma ise (ve (2) 'de olduğu gibi, "Per" daha sonra nesneye map ( source )bağlı bir yöntemle bir nesne döndürür dönüştür - nerede

"ruleName" Per ( subjectTransform [ , ruleName ]), isteğe bağlıdır ve <xsl: call-template name = "templateName"> ... benzeri işlevler sağlar)

yani, Per :: ( Dönüştür [, ruleName :: String ]) -->{map :: ( AnyValue --> AnyValue )}

ile

Dönüşüm :: {$ :: Yeniden yazma kuralları dizisi [rw.r.] }

( [rw.r.] yüklem ve şablon işlev çiftleri)

örneğin, verilen (... başka bir örnek)

// (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);
      }
  ]
//...
] };

sonra

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

verim:

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

süre ... (çok benzer <xsl:call-template name="betterGenderString">...)

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

verim:

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

ve

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

verim:

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

4) Aksi takdirde

kimlik fonksiyonu , diğer tüm durumlarda

yani, Per :: T --> T

(yani, Per === function ( value ) { return value ; })

Not

yukarıdaki (3) 'te, bir şablon işlevinin gövdesindeki bir JavaScript'in "bu" ifadesi bu nedenle kapsayıcıya / sahip Transform'a ve kural kümesine ($: [...] dizisi tarafından tanımlandığı gibi) bağlıdır - bu nedenle, "Per (this)" ifadesini bu bağlamda, XSLT'lere işlevsel olarak yakın bir eşdeğer yapmak

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

'HTH,


1
Bu oldukça havalı.
Robert Harvey

@RobertHarvey: bir kısa ve özlü oluşu yanında bölüm 5.1 Ben uzun zaman önce fark ettiğini ve kendisini, ben sonunda da ilgisini gördü ve Evan Lenz akılda kalıcı sözler esinlenerek, at "XSLT düşündüğünüzden daha basittir!" Http: // www. lenzconsulting.com/how-xslt-works - ve bu yüzden JavaScript'in çok dövülebilir bir dilde bu iddiayı (sadece meraktan dolayı) doğrulamak için bir şans vermeye karar verdim.
YSharp

Ayrıntılı cevabınız için çok teşekkür ederim. Başka şeyler ile meşgulüm (kendi XSLT eşdeğüm dahil), ancak daha dikkatli bir görünüm elde etmek için buna geri dönmek niyetindeyim.
Brett Zamir

3

Son zamanlarda tam olarak bu amaç için bir kütüphane, json-transforms oluşturdum :

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

Doğrudan XSLT'den esinlenerek JSPath , XPath üzerinde modellenmiş bir DSL ve yinelemeli desen eşleştirme yaklaşımının bir kombinasyonunu kullanır .

İşte kısa bir örnek. Aşağıdaki JSON nesnesi verildiğinde:

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

İşte bir dönüşüm:

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);

Aşağıdaki çıktı hangi:

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

Bu dönüşüm üç kuraldan oluşur. Birincisi, Honda tarafından üretilen, bir Hondamülke sahip bir nesne yayan , daha sonra tekrarlayan eşleşen herhangi bir otomobille eşleşir . İkinci kural maker, modelve yearözelliklerinin çıktısını alan herhangi bir nesneyle bir özellik ile eşleşir . Son, özyinelemeli olarak eşleşen kimlik dönüşümüdür.


+1 ve bilgi için teşekkürler. Kendi github.com/brettz9/jtlt'ımı bir noktada tamamlamayı umuyorum , ancak karşılaştırmak için daha fazla uygulamaya sahip olmak yardımcı olur.
Brett Zamir

-1

Ben hiç JSON başına JSON varyant elde edeceğini sanmıyorum. Python'dan Jinja2, JavaScripts Nunjucks, Groovy MarkupTemplateEngine ve istediğiniz şeylere çok uygun olması gereken birçok cazip motor var. .NET'in ayrıca T4 ve JSON serileştirme / serileştirme desteği vardır.

Derserialize JSON verileri temelde bir sözlük veya harita yapısı olacağı için, bu sadece şablonlama motorunuza geçecek ve orada istenen düğümler üzerinde yineleyeceksiniz. JSON verileri daha sonra şablon tarafından dönüştürülür.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.