XSLT equivalente para JSON

13

Estaba interesado en encontrar (o, si fuera necesario, desarrollar) un equivalente XSLT para JSON.

Como no encontré ninguno, estaba considerando el posible lenguaje de consulta para usar para hacer coincidir las rutas JSON a fin de aplicar plantillas (desde JavaScript) cuando existía una coincidencia (probablemente solo estaba revisando una matriz de patrones coincidentes en orden, y parando en la primera plantilla que coincida, aunque permitiendo el equivalente de xsl: apply-templates para mantener las plantillas funcionando para los niños).

Soy consciente de los lenguajes de consulta JSONPath, JSONQuery y RQL como JSON (aunque no estaba completamente claro si RQL era compatible con rutas absolutas y relativas). Cualquier sugerencia sobre los factores a considerar y las ventajas relativas de cada uno hacia dicho uso.

    
pregunta Brett Zamir 05.12.2014 - 22:14

5 respuestas

25

XML: XSLT :: JSON: x . ¿Qué es x ?

La respuesta más fácil sería x = JavaScript. A pesar de que podría hacer un caso para esto, se siente insatisfactorio. A pesar de que XSLT es técnicamente Turing complete , hay una mala correspondencia entre declarative estilo de XSLT y los estilos más imperativos o funcionales vistos en JavaScript.

Hay algunos lenguajes de consulta JSON independientes, como JSONPath , JSONiq , y RQL que podría representar el término medio de XML: XPath :: JSON: y (o posiblemente, XQuery en lugar de XPath). Y cada base de datos de documentos centrada en JSON tiene un lenguaje de consulta relacionado con JSON .

Pero la realidad es que, a pesar de que hay algunos contendientes para la posición XSLT completa, como SpahQL , no hay equivalentes JSON ampliamente aceptados y ampliamente admitidos a XSLT.

¿Por qué ?

Con todos los JSON en el mundo, ¿por qué no hay un (más directo) análogo a XSLT? Porque muchos desarrolladores ven XSLT como un experimento fallido. Cualquier motor de búsqueda llevará a citas como "XSLT es una falla envuelta en el dolor". Otros han argumentado que si se formateara mejor, sería más popular. Pero el interés en XSLT generalmente ha disminuido con los años . Muchas herramientas que lo admiten solo admiten versión 1.0 , que es una especificación de 1999. ¿Quince años de antigüedad? Hay una especificación 2.0 mucho más nueva, y si la gente estuviera entusiasmada con XSLT, sería compatible. No lo es

Los desarrolladores en general han optado por procesar y transformar documentos XML con código, no con plantillas de transformación. Por lo tanto, no es sorprendente que al trabajar con JSON, también decidan hacerlo en su idioma nativo, en lugar de agregar un sistema de transformación "externo" adicional.

    
respondido por el Jonathan Eunice 06.12.2014 - 00:08
7

Aunque Jonathan habla en gran medida sobre la naturaleza de XSLT como lenguaje en su respuesta, creo que hay otro ángulo a considerar.

El propósito de XSLT era transformar documentos XML en algún otro documento (XML, HTML, SGML, PDF, etc.). De esta manera, XSLT se usa con frecuencia, efectivamente, como lenguaje de plantilla.

Hay una gran variedad de bibliotecas de plantillas por ahí, incluso si se restringe a bibliotecas de JavaScript (que no debería necesitar, ya que JS en JSON solo se refiere a la génesis de la notación y no debe tomarse para implica que JSON es solo para JavaScript). Este selector de motor de plantilla proporciona una indicación de la variedad de opciones de JS que hay por ahí.

La última mitad de sus preguntas habla más sobre los lenguajes de consulta y la versión XML de estos sería XPath (no XSLT). Como mencionaste, hay una variedad de opciones allí y no tengo nada que agregar a esa lista. Esta área es relativamente nueva, por lo que te sugiero que elijas una y la sigas.

    
respondido por el Dancrumb 06.12.2014 - 22:04
3

Aquí hay algunos ejemplos de lo que puedes hacer con mi (pequeño [jslt.min.js] ) JSLT - JavaScript Lightweight Transforms:

enlace

( [jslt.min.js] pesa ~ 3.1kb minified )

es decir, solo una función,

function Per ( subject ) { ... }

... que en realidad imita a modelo de procesamiento de XSLT (1.0) .

(consulte las funciones internas de "transformación" y "plantilla", en el cuerpo de Per)

Entonces, en esencia, es simplemente todo integrado en ese único function Per ( subject ) { ... } que resume su evaluación sobre el tipo de su (también) único argumento, para implementar, ya sea:

1) Array sujeto

creación / filtrado / aplanamiento / agrupamiento / pedido / etc del conjunto de nodos , si el sujeto es una matriz, donde el conjunto de nodos resultante (un Array también) se extiende con, y enlazado a los métodos nombrados en consecuencia ( solo la instancia devuelta Array de la llamada a Per ( subjectArray ) se extiende; es decir, Array.prototype se deja sin tocar)

es decir, Por :: Array --> Array

(los métodos de extensión de Array resultantes tienen nombres que se explican por sí mismos como, groupBy, orderBy, flattenBy, etc. - consulte el uso en los ejemplos)

2) Cadena tema

interpolación de cadena , si el asunto es una cadena

("Per" luego devuelve un objeto con un método map ( source ) , que está enlazado al sujeto template cadena)

es decir, Por :: String --> {map :: ( AnyValue --> String )}

por ejemplo,

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

rendimientos:

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

mientras que cualquiera de

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

o

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

produce lo mismo:

"Those '0123456789' are our 10 digits."

pero solo

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

rendimientos

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

3) Transformar tema

Transformación parecida a XSLT , si el tema es un hash con un miembro definido convencionalmente "$" que proporciona el conjunto de reglas de reescritura (y lo mismo que en ( 2), "Per" luego devuelve un objeto con un método map ( source ) enlazado a la transformación del sujeto - donde

"ruleName" en Per ( subjectTransform [ , ruleName ]) es opcional y proporciona una funcionalidad similar a < xsl: call-template name="templateName" > ...)

es decir, Per :: ( Transform [ ruleName :: String ]) --> {map :: ( AnyValue --> AnyValue )}

con

Transformar :: {$ :: Array de las reglas de reescritura [rw.r.] }

( [rw.r.] pares de función de predicado y plantilla)

por ejemplo, dado (... otro ejemplo artificial)

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

entonces

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

rendimientos:

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

mientras que ... (muy parecido a <xsl:call-template name="betterGenderString">... )

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

rendimientos:

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

y

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

rendimientos:

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

4) De lo contrario

la función de identidad , en todos los demás casos

es decir, Por :: T --> T

(es decir, Per === function ( value ) { return value ; } )

Nota

en (3) arriba, un "esto" de JavaScript en el cuerpo de una función de plantilla está vinculado al contenedor / propietario Transform y su conjunto de reglas (como se define en $: [ ...] array) - por lo tanto, haciendo de la expresión "Per (this)", en ese contexto, un equivalente funcionalmente cercano al de XSLT

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

'HTH,

    
respondido por el YSharp 04.03.2016 - 02:50
2

Recientemente creé una biblioteca, json-transforms , exactamente para este propósito:

enlace

Utiliza una combinación de JSPath , un DSL modelado en XPath y un enfoque de búsqueda de patrones recursivos, inspirado directamente por XSLT.

Aquí hay un ejemplo rápido. Dado el siguiente objeto 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 }
  ]
};

Aquí hay una transformación:

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

Que da como resultado lo siguiente:

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

Esta transformación se compone de tres reglas. El primero coincide con cualquier automóvil fabricado por Honda, emitiendo un objeto con una propiedad Honda y luego haciendo coincidencias recursivas. La segunda regla coincide con cualquier objeto con una propiedad maker , dando salida a las propiedades model y year . La final es la transformación de identidad que coincide de manera recursiva.

    
respondido por el ColinE 10.07.2016 - 19:41
-1

No creo que alguna vez obtengas una variante JSON para JSON per se. Existen varios motores de plantillas, como Jinja2 de Python, JavaScripts Nunjucks, Groovy MarkupTemplateEngine y muchos otros que deberían ser adecuados para lo que usted desea. .NET tiene soporte para deserialización / serialización T4 y JSON, por lo que también lo tiene.

Dado que los datos JSON desererializados serían básicamente un diccionario o una estructura de mapa, eso solo pasaría a su motor de plantillas e iteraría sobre los nodos deseados allí. Los datos JSON luego se transforman por la plantilla.

    
respondido por el greenaj 21.01.2015 - 22:26

Lea otras preguntas en las etiquetas