JSON 的 XSLT 等效项

发布于 2024-08-08 08:02:32 字数 1540 浏览 6 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(25

眉黛浅 2024-08-15 08:02:32

JSON 的 XSLT 等效项 - 候选列表(工具和规范)

工具

1。 XSLT

您可以使用 XSLT for JSON 旨在 fn:json-to-xml

本节介绍允许使用 XSLT 处理 JSON 数据的工具。

2. jq

jq 就像 JSON 数据的 sed - 您可以使用它来切片、过滤、映射和转换结构化数据,就像 sed、awk、grep 和朋友让您处理文本一样轻松。
有针对不同操作系统的安装包。

3. jj

JJ 是一个命令行实用程序,它提供了一种快速而简单的方法来检索或更新 JSON 文档中的值。它的底层由 GJSON 和 SJSON 提供支持。

4. fx

命令行 JSON 处理工具

  • 不需要学习新语法
  • 纯 JavaScript
  • 格式设置和突出显示
  • 独立二进制文件

5. CsvCruncher

基于SQL的命令行表格数据处理工具

  • 不需要学习新语法
  • 适用于 JSON 包含具有相似项的大型数组时
  • 支持将多个文档作为多个SQL表进行处理
  • 用 Kotlin 编写,在 Java 上运行
  • 也可作为 Maven 中央存储库中的 Java 库

6. jl

jl(“JSON lambda”)是一种用于查询和操作 JSON 的小型函数式语言。

7. JOLT

用 Java 编写的 JSON 到 JSON 转换库,其中转换的“规范”本身就是一个 JSON 文档。

8. gron

使 JSON 可 grep 化!
gron 将 JSON 转换为离散赋值,以便更轻松地 grep 查找您想要的内容并查看它的绝对“路径”。它简化了对返回大量 JSON 但文档很糟糕的 API 的探索。

9. json-e

JSON-e 是一个数据结构参数化系统,用于在 JSON 对象中嵌入上下文。
中心思想是将数据结构视为“模板”,并使用另一个数据结构作为上下文对其进行转换,以生成输出数据结构。

10. JSLT

JSLT 是一种完整的 JSON 查询和转换语言。语言设计的灵感来自 jq、XPath 和 XQuery。

11. JSONata

JSONata 是一种轻量级的 JSON 数据查询和转换语言。受到 XPath 3.1 的“位置路径”语义的启发,它允许以紧凑且直观的符号来表达复杂的查询。

12. JSONPath Plus

分析、转换并有选择地从 JSON 文档(和 JavaScript 对象)中提取数据。
jsonpath-plus 在原始规范的基础上进行了扩展,添加了一些额外的运算符,并明确了原始规范中未阐明的一些行为。

13. json-transforms 最后提交时间:2017 年 12 月 1 日

提供一种递归的模式匹配方法来转换 JSON 数据。转换被定义为与 JSON 对象的结构相匹配的一组规则。当发生匹配时,规则会发出转换后的数据,并可选择递归以转换子对象。

14. json 最后提交时间:2018 年 6 月 23 日

json 是一个用于处理 JSON 的快速 CLI 工具。它是一个单文件 Node.js 脚本,没有外部依赖(除了 Node.js 本身)。

15. jsawk 最后提交时间:2015 年 3 月 4 日

Jsawk 类似于 awk,但用于 JSON。您使用从 stdin 读取的 JSON 对象数组,使用 JavaScript 过滤它们以生成打印到 stdout 的结果数组。

16. yate 最后提交时间:2017 年 3 月 13 日

测试可以用作文档https://github.com/pasaran/yate /树/主/测试

17. jsonpath-object-transform 最后提交时间:2017 年 1 月 18 日

使用 JSONPath 从对象文字中提取数据并基于模板生成新对象。

18. 装订 最后提交时间:2013 年 9 月 16 日

Stapling 是一个 JavaScript 库,支持 JSON 对象的 XSLT 格式设置。
Stapling 不使用 JavaScript 模板引擎和 text/html 模板,而是让您有机会使用 XSLT 模板(通过 Ajax 异步加载,然后缓存客户端)来解析 JSON 数据源。

19. mapneat

MapNeat 是一个用 Kotlin 编写的 JVM 库,它提供了一种易于使用的 DSL(领域特定语言),用于以声明方式将 JSON 转换为 JSON、XML 转换为 JSON、POJO 转换为 JSON。

20。 DTL

DTL 的主要优势之一是它与 JavaScript 的兼容性,这意味着您可以在任何可以使用 JavaScript 的地方使用它。 DTL 的用途也非常广泛,可用于在各种场景中操作数据,包括处理来自表单或 API 调用的输入数据以及在数据格式之间进行转换。

规格:

JSON 指针是一种字符串语法或地址,用于标识较大 JSON 对象中的特定对象。它没有查询功能或转换功能。 JSON 指针的指示对象可以是任何 JSON 对象。

JSONPath 表达式始终引用 JSON 结构,就像 XPath 表达式与 XML 文档结合使用一样

JSON 的 JSPath 就像 XML 的 XPath。”

JSONiq 背后的主要灵感来源是 XQuery,迄今为止,它已被证明是一种成功且高效的半结构化数据查询语言

JMESPath 是一种 JSON 查询语言。 JMESPath语言采用ABNF语法描述,具有完整的规范。

XSLT equivalents for JSON - a list of candidates (tools and specs)

Tools

1. XSLT

You can use XSLT for JSON with the aim of fn:json-to-xml.

This section describes facilities allowing JSON data to be processed using XSLT.

2. jq

jq is like sed for JSON data - you can use it to slice and filter and map and transform structured data with the same ease that sed, awk, grep and friends let you play with text.
There are install packages for different OS.

3. jj

JJ is a command line utility that provides a fast and simple way to retrieve or update values from JSON documents. It's powered by GJSON and SJSON under the hood.

4. fx

Command-line JSON processing tool

  • Don't need to learn new syntax
  • Plain JavaScript
  • Formatting and highlighting
  • Standalone binary

5. CsvCruncher

Command-line tabular data SQL-based processing tool

  • Don't need to learn new syntax
  • Suitable when JSON contains a large array with similar items
  • Supports multiple documents to be processed as multiple SQL tables
  • Written in Kotlin, runs on Java
  • Also available as a Java library in Maven Central repository

6. jl

jl ("JSON lambda") is a tiny functional language for querying and manipulating JSON.

7. JOLT

JSON to JSON transformation library written in Java where the "specification" for the transform is itself a JSON document.

8. gron

Make JSON greppable!
gron transforms JSON into discrete assignments to make it easier to grep for what you want and see the absolute 'path' to it. It eases the exploration of APIs that return large blobs of JSON but have terrible documentation.

9. json-e

JSON-e is a data-structure parameterization system for embedding context in JSON objects.
The central idea is to treat a data structure as a "template" and transform it, using another data structure as context, to produce an output data structure.

10. JSLT

JSLT is a complete query and transformation language for JSON. The language design is inspired by jq, XPath, and XQuery.

11. JSONata

JSONata is a lightweight query and transformation language for JSON data. Inspired by the 'location path' semantics of XPath 3.1, it allows sophisticated queries to be expressed in a compact and intuitive notation.

12. JSONPath Plus

Analyse, transform, and selectively extract data from JSON documents (and JavaScript objects).
jsonpath-plus expands on the original specification to add some additional operators and makes explicit some behaviors the original did not spell out.

13. json-transforms Last Commit Dec 1, 2017

Provides a recursive, pattern-matching approach to transforming JSON data. Transformations are defined as a set of rules which match the structure of a JSON object. When a match occurs, the rule emits the transformed data, optionally recursing to transform child objects.

14. json Last commit Jun 23, 2018

json is a fast CLI tool for working with JSON. It is a single-file node.js script with no external deps (other than node.js itself).

15. jsawk Last commit Mar 4, 2015

Jsawk is like awk, but for JSON. You work with an array of JSON objects read from stdin, filter them using JavaScript to produce a results array that is printed to stdout.

16. yate Last Commit Mar 13, 2017

Tests can be used as docu https://github.com/pasaran/yate/tree/master/tests

17. jsonpath-object-transform Last Commit Jan 18, 2017

Pulls data from an object literal using JSONPath and generate a new objects based on a template.

18. Stapling Last Commit Sep 16, 2013

Stapling is a JavaScript library that enables XSLT formatting for JSON objects.
Instead of using a JavaScript templating engine and text/html templates, Stapling gives you the opportunity to use XSLT templates - loaded asynchronously with Ajax and then cached client side - to parse your JSON datasources.

19. mapneat

MapNeat is a JVM library written in Kotlin that provides an easy to use DSL (Domain Specific Language) for transforming JSON to JSON, XML to JSON, POJO to JSON in a declarative way.

20. DTL

One of the key advantages of DTL is its compatibility with JavaScript, which means you can use it anywhere you can use JavaScript. DTL is also incredibly versatile and can be used to manipulate data in a variety of scenarios, including handling input data from forms or API calls and converting between data formats.

Specs:

JSON Pointer is a string syntax or address to identify a specific object within a larger JSON object. It does not have querying features or transformation functions. The referent of a JSON Pointer can be any JSON object.

JSONPath expressions always refer to a JSON structure in the same way as XPath expression are used in combination with an XML document

JSPath for JSON is like XPath for XML."

The main source of inspiration behind JSONiq is XQuery, which has been proven so far a successful and productive query language for semi-structured data

JMESPath is a query language for JSON. The JMESPath language is described in an ABNF grammar with a complete specification.

酒废 2024-08-15 08:02:32

有趣的想法。在 Google 上进行的一些搜索产生了一些有趣的页面,其中包括:

希望这会有所帮助。

Interesting idea. Some searching on Google produced a few pages of interest, including:

Hope this helps.

oО清风挽发oО 2024-08-15 08:02:32

尝试JOLT。它是一个用 Java 编写的 JSON 到 JSON 转换库。

它是专门创建的,因为我们不想玩“JSON -> XML -> XSLT -> XML -> JSON”游戏,并且使用模板进行任何足够复杂的转换是无法维护的。

Try JOLT. It is a JSON to JSON transformation library written in Java.

It was created specifically because we did not want to play the "JSON -> XML -> XSLT -> XML -> JSON" game, and using a template for any sufficiently complex transform is unmaintainable.

墟烟 2024-08-15 08:02:32

XSLT 支持 JSON,如 http://www.w3.org/TR/xslt- 所示30/#json

XML 使用尖括号作为分隔符,JSON 使用大括号、方括号……即XML 较少的标记识别比较意味着它针对声明性转换进行了优化,而更多的比较(如 switch 语句)出于速度原因假设推测分支预测,而脚本语言中的命令式代码对此很有用。作为直接结果,对于半结构化数据的不同组合,您可能希望将 XSLT 和 JavaScript 引擎的性能作为响应式页面的一部分进行基准测试。对于可忽略不计的数据负载,转换可能与无需 XML 序列化的 JSON 一样有效。 W3的决定应该基于更好的分析。

XSLT supports JSON as seen at http://www.w3.org/TR/xslt-30/#json

XML uses angular brackets for delimiter tokens, JSON uses braces, square brackets, ... I. e. XML's fewer token recognition comparisons means it's optimized for declarative transformation, whereas more comparisons, being like switch statement, for speed reasons assume speculative branch prediction that imperative code in scripting languages is useful for. As direct consequence, for different mixes of semi-structured data, you may want to benchmark XSLT and javascript engines' performance as part of responsive pages. For negligible data payload, transformations might work just as well with JSON without XML serialization. W3's decision ought to be based on better analysis.

许你一世情深 2024-08-15 08:02:32

jq - 轻量级、灵活的命令行 JSON 处理器

它不像 XSLT 那样基于模板,但更简洁。例如,将 nameaddress 字段提取到数组中: [.name, .address]

教程 演练了转换 Twitter 的 JSON API 的示例(以及 手册 有很多例子)。

jq - lightweight and flexible command-line JSON processor

It's not template-based like XSLT, but more concise. e.g. to extract name and address fields into an array: [.name, .address]

The tutorial walks through an example of transforming Twitter's JSON API (and the manual has many examples).

野味少女 2024-08-15 08:02:32

我最近发现了一个我喜欢的 JSON 样式工具: https://github.com/twigkit/tempo。非常容易使用的工具——在我看来,它比 XSLT 更容易使用——不需要 XPATH 查询。

I recently found a tool that I love for styling JSON: https://github.com/twigkit/tempo. Very easy tool to use--in my opinion, it is much easier to work with than XSLT--no need for XPATH queries.

淡墨 2024-08-15 08:02:32

最近,我围绕此编写了自己的小型库,它试图尽可能接近

5.1处理模型(XSLT REC)
https://www.w3.org/TR/xslt#section-Processing-Model

尽可能地(无论如何我都可以),用几行 JavaScript 代码。

以下是一些不完全简单的使用示例...

1. JSON 到某些标记:

Fiddle: https://jsfiddle.net/YSharpLanguage/kj9pk8oz/10

(灵感来自D.1 文档示例 (XSLT REC) https://www.w3.org/TR/xslt#section-Document-Example)

其中:

var D1document = {
    type: "document", title: [ "Document Title" ],
    "": [
      { type: "chapter", title: [ "Chapter Title" ],
        "": [
        { type: "section", title: [ "Section Title" ],
          "": [
            { type: "para", "": [ "This is a test." ] },
            { type: "note", "": [ "This is a note." ] }
        ] },
        { type: "section", title: [ "Another Section Title" ],
          "": [
            { type: "para", "": [ "This is ", { emph: "another" }, " test." ] },
            { type: "note", "": [ "This is another note." ] }
        ] }
      ] }
    ] };

var D1toHTML = { $: [
  [ [ function(node) { return node.type === "document"; } ],
    function(root) {
      return "<html>\r\n\
  <head>\r\n\
    <title>\r\n\
      {title}\r\n".of(root) + "\
    </title>\r\n\
  </head>\r\n\
  <body>\r\n\
{*}".of(root[""].through(this)) + "\
  </body>\r\n\
</html>";
    }
  ],
  [ [ function(node) { return node.type === "chapter"; } ],
    function(chapter) {
      return "    <h2>{title}</h2>\r\n".of(chapter) + "{*}".of(chapter[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "section"; } ],
    function(section) {
      return "    <h3>{title}</h3>\r\n".of(section) + "{*}".of(section[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "para"; } ],
    function(para) {
      return "    <p>{*}</p>\r\n".of(para[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "note"; } ],
    function(note) {
      return '    <p class="note"><b>NOTE: </b>{*}</p>\r\n'.of(note[""].through(this));
    }
  ],
  [ [ function(node) { return node.emph; } ],
    function(emph) {
      return "<em>{emph}</em>".of(emph);
    }
  ]
] };

console.log(D1document.through(D1toHTML));

... 给出:

<html>
  <head>
    <title>
      Document Title
    </title>
  </head>
  <body>
    <h2>Chapter Title</h2>
    <h3>Section Title</h3>
    <p>This is a test.</p>
    <p class="note"><b>NOTE: </b>This is a note.</p>
    <h3>Another Section Title</h3>
    <p>This is <em>another</em> test.</p>
    <p class="note"><b>NOTE: </b>This is another note.</p>
  </body>
</html>

2. JSON 到 JSON:

小提琴: https://jsfiddle.net/YSharpLanguage/ppfmmu15/10

其中:

// (A "Company" is just an object with a "Team")
function Company(obj) {
  return obj.team && Team(obj.team);
}

// (A "Team" is just a non-empty array that contains at least one "Member")
function Team(obj) {
  return ({ }.toString.call(obj) === "[object Array]") &&
         obj.length &&
         obj.find(function(item) { return Member(item); });
}

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

function Dude(obj) {
  return Member(obj) && (obj.sex === "Male");
}

function Girl(obj) {
  return Member(obj) && (obj.sex === "Female");
}

var data = { team: [
  { first: "John", last: "Smith", sex: "Male" },
  { first: "Vaio", last: "Sony" },
  { first: "Anna", last: "Smith", sex: "Female" },
  { first: "Peter", last: "Olsen", sex: "Male" }
] };

var TO_SOMETHING_ELSE = { $: [

  [ [ Company ],
    function(company) {
      return { some_virtual_dom: {
        the_dudes: { ul: company.team.select(Dude).through(this) },
        the_grrls: { ul: company.team.select(Girl).through(this) }
      } }
    } ],

  [ [ Member ],
    function(member) {
      return { li: "{first} {last} ({sex})".of(member) };
    } ]

] };

console.log(JSON.stringify(data.through(TO_SOMETHING_ELSE), null, 4));

... 给出:

{
    "some_virtual_dom": {
        "the_dudes": {
            "ul": [
                {
                    "li": "John Smith (Male)"
                },
                {
                    "li": "Peter Olsen (Male)"
                }
            ]
        },
        "the_grrls": {
            "ul": [
                {
                    "li": "Anna Smith (Female)"
                }
            ]
        }
    }
}

3. XSLT 与 JavaScript:

JavaScript 等价于...

XSLT 3.0 REC 第 14.4 节示例:根据公共值对节点进行分组

(位于:http:// jsfiddle.net/YSharpLanguage/8bqcd0ey/1

比照。 https://www.w3.org/TR/xslt-30/#grouping -examples

其中...

var cities = [
  { name: "Milano",  country: "Italia",      pop: 5 },
  { name: "Paris",   country: "France",      pop: 7 },
  { name: "München", country: "Deutschland", pop: 4 },
  { name: "Lyon",    country: "France",      pop: 2 },
  { name: "Venezia", country: "Italia",      pop: 1 }
];

/*
  Cf.
  XSLT 3.0 REC Section 14.4
  Example: Grouping Nodes based on Common Values

  https://www.w3.org/TR/xslt-30/#grouping-examples
*/
var output = "<table>\r\n\
  <tr>\r\n\
    <th>Position</th>\r\n\
    <th>Country</th>\r\n\
    <th>City List</th>\r\n\
    <th>Population</th>\r\n\
  </tr>{*}\r\n\
</table>".of
  (
    cities.select().groupBy("country")(function(byCountry, index) {
      var country = byCountry[0],
          cities = byCountry[1].select().orderBy("name");
      return "\r\n\
  <tr>\r\n\
    <td>{position}</td>\r\n\
    <td>{country}</td>\r\n\
    <td>{cities}</td>\r\n\
    <td>{population}</td>\r\n\
  </tr>".
        of({ position: index + 1, country: country,
             cities: cities.map(function(city) { return city.name; }).join(", "),
             population: cities.reduce(function(sum, city) { return sum += city.pop; }, 0)
           });
    })
  );

... 给出:

<table>
  <tr>
    <th>Position</th>
    <th>Country</th>
    <th>City List</th>
    <th>Population</th>
  </tr>
  <tr>
    <td>1</td>
    <td>Italia</td>
    <td>Milano, Venezia</td>
    <td>6</td>
  </tr>
  <tr>
    <td>2</td>
    <td>France</td>
    <td>Lyon, Paris</td>
    <td>9</td>
  </tr>
  <tr>
    <td>3</td>
    <td>Deutschland</td>
    <td>München</td>
    <td>4</td>
  </tr>
</table>

4. JSONiq 与 JavaScript:

相当于...

JSONiq 用例第 1.1.2 节。 JSON 分组查询

(位于:https://jsfiddle.net/YSharpLanguage/hvo24hmk/3< /a>)

参见。 http://jsoniq.org/docs/JSONiq-usecases/html -single/index.html#jsongrouping

其中...

/*
  1.1.2. Grouping Queries for JSON
  http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping
*/
var sales = [
  { "product" : "broiler", "store number" : 1, "quantity" : 20  },
  { "product" : "toaster", "store number" : 2, "quantity" : 100 },
  { "product" : "toaster", "store number" : 2, "quantity" : 50 },
  { "product" : "toaster", "store number" : 3, "quantity" : 50 },
  { "product" : "blender", "store number" : 3, "quantity" : 100 },
  { "product" : "blender", "store number" : 3, "quantity" : 150 },
  { "product" : "socks", "store number" : 1, "quantity" : 500 },
  { "product" : "socks", "store number" : 2, "quantity" : 10 },
  { "product" : "shirt", "store number" : 3, "quantity" : 10 }
];

var products = [
  { "name" : "broiler", "category" : "kitchen", "price" : 100, "cost" : 70 },
  { "name" : "toaster", "category" : "kitchen", "price" : 30, "cost" : 10 },
  { "name" : "blender", "category" : "kitchen", "price" : 50, "cost" : 25 },
  {  "name" : "socks", "category" : "clothes", "price" : 5, "cost" : 2 },
  { "name" : "shirt", "category" : "clothes", "price" : 10, "cost" : 3 }
];

var stores = [
  { "store number" : 1, "state" : "CA" },
  { "store number" : 2, "state" : "CA" },
  { "store number" : 3, "state" : "MA" },
  { "store number" : 4, "state" : "MA" }
];

var nestedGroupingAndAggregate = stores.select().orderBy("state").groupBy("state")
( function(byState) {
    var state = byState[0],
        stateStores = byState[1];
    byState = { };
    return (
      (
        byState[state] =
        products.select().orderBy("category").groupBy("category")
        ( function(byCategory) {
            var category = byCategory[0],
                categoryProducts = byCategory[1],
                categorySales = sales.filter(function(sale) {
                  return stateStores.find(function(store) { return sale["store number"] === store["store number"]; }) &&
                         categoryProducts.find(function(product) { return sale.product === product.name; });
                });
            byCategory = { };
            return (
              (
                byCategory[category] =
                categorySales.select().orderBy("product").groupBy("product")
                ( function(byProduct) {
                    var soldProduct = byProduct[0],
                        soldQuantities = byProduct[1];
                    byProduct = { };
                    return (
                      (
                        byProduct[soldProduct] =
                        soldQuantities.reduce(function(sum, sale) { return sum += sale.quantity; }, 0)
                      ),
                      byProduct
                    );
                } ) // byProduct()
              ),
              byCategory
            );
        } ) // byCategory()
      ),
      byState
    );
} ); // byState()

...给出:

[
  {
    "CA": [
      {
        "clothes": [
          {
            "socks": 510
          }
        ]
      },
      {
        "kitchen": [
          {
            "broiler": 20
          },
          {
            "toaster": 150
          }
        ]
      }
    ]
  },
  {
    "MA": [
      {
        "clothes": [
          {
            "shirt": 10
          }
        ]
      },
      {
        "kitchen": [
          {
            "blender": 250
          },
          {
            "toaster": 50
          }
        ]
      }
    ]
  }
]

克服 JSONPath wrt 的限制也很有用。针对祖先轴进行查询,如这个SO问题提出的(当然还有其他人)。

例如,如何在知道其品牌 ID 的情况下获得杂货商品的折扣

{
 "prods": [
    {
        "info": {
              "rate": 85
                },
        "grocery": [
                 {
                  "brand": "C",
                  "brand_id": "984"
                 },
                 {
                  "brand": "D",
                  "brand_id": "254"
                 }
                 ],
         "discount": "15"
    },
    {
        "info": {
              "rate": 100
                },
        "grocery": [
                 {
                  "brand": "A",
                  "brand_id": "983"
                 },
                 {
                  "brand": "B",
                  "brand_id": "253"
                 }
                 ],
         "discount": "20"
     }
 ]
}

一个可能的解决方案是:

var products = {
     "prods": [
        {
            "info": {
                  "rate": 85
                    },
            "grocery": [
                     {
                      "brand": "C",
                      "brand_id": "984"
                     },
                     {
                      "brand": "D",
                      "brand_id": "254"
                     }
                     ],
             "discount": "15"
        },
        {
            "info": {
                  "rate": 100
                    },
            "grocery": [
                     {
                      "brand": "A",
                      "brand_id": "983"
                     },
                     {
                      "brand": "B",
                      "brand_id": "253"
                     }
                     ],
             "discount": "20"
         }
     ]
};

function GroceryItem(obj) {
  return (typeof obj.brand === "string") && (typeof obj.brand_id === "string");
}

    // last parameter set to "true", to grab all the "GroceryItem" instances
    // at any depth:
var itemsAndDiscounts = [ products ].nodeset(GroceryItem, true).
    map(
      function(node) {
        var item = node.value, // node.value: the current "GroceryItem" (aka "$.prods[*].grocery[*]")

            discount = node.parent. // node.parent: the array of "GroceryItem" (aka "$.prods[*].grocery")
                       parent. // node.parent.parent: the product (aka "$.prods[*]")
                       discount; // node.parent.parent.discount: the product discount

        // finally, project into an easy-to-filter form:
        return { id: item.brand_id, discount: discount };
      }
    ),
    discountOfItem983;

discountOfItem983 = itemsAndDiscounts.
  filter
  (
    function(mapped) {
      return mapped.id === "983";
    }
  )
  [0].discount;

console.log("Discount of #983: " + discountOfItem983);

...给出:

Discount of #983: 20

'HTH,

I wrote my own small library around this, recently, which tries to stay as close to

5.1 Processing Model (XSLT REC)
https://www.w3.org/TR/xslt#section-Processing-Model

as is possible (as I could anyway), in a few lines of JavaScript code.

Here are a few not-completely-trivial examples of use...

1. JSON-to-some-markup:

Fiddle: https://jsfiddle.net/YSharpLanguage/kj9pk8oz/10

(inspired by D.1 Document Example (XSLT REC) https://www.w3.org/TR/xslt#section-Document-Example)

where this:

var D1document = {
    type: "document", title: [ "Document Title" ],
    "": [
      { type: "chapter", title: [ "Chapter Title" ],
        "": [
        { type: "section", title: [ "Section Title" ],
          "": [
            { type: "para", "": [ "This is a test." ] },
            { type: "note", "": [ "This is a note." ] }
        ] },
        { type: "section", title: [ "Another Section Title" ],
          "": [
            { type: "para", "": [ "This is ", { emph: "another" }, " test." ] },
            { type: "note", "": [ "This is another note." ] }
        ] }
      ] }
    ] };

var D1toHTML = { $: [
  [ [ function(node) { return node.type === "document"; } ],
    function(root) {
      return "<html>\r\n\
  <head>\r\n\
    <title>\r\n\
      {title}\r\n".of(root) + "\
    </title>\r\n\
  </head>\r\n\
  <body>\r\n\
{*}".of(root[""].through(this)) + "\
  </body>\r\n\
</html>";
    }
  ],
  [ [ function(node) { return node.type === "chapter"; } ],
    function(chapter) {
      return "    <h2>{title}</h2>\r\n".of(chapter) + "{*}".of(chapter[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "section"; } ],
    function(section) {
      return "    <h3>{title}</h3>\r\n".of(section) + "{*}".of(section[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "para"; } ],
    function(para) {
      return "    <p>{*}</p>\r\n".of(para[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "note"; } ],
    function(note) {
      return '    <p class="note"><b>NOTE: </b>{*}</p>\r\n'.of(note[""].through(this));
    }
  ],
  [ [ function(node) { return node.emph; } ],
    function(emph) {
      return "<em>{emph}</em>".of(emph);
    }
  ]
] };

console.log(D1document.through(D1toHTML));

... gives:

<html>
  <head>
    <title>
      Document Title
    </title>
  </head>
  <body>
    <h2>Chapter Title</h2>
    <h3>Section Title</h3>
    <p>This is a test.</p>
    <p class="note"><b>NOTE: </b>This is a note.</p>
    <h3>Another Section Title</h3>
    <p>This is <em>another</em> test.</p>
    <p class="note"><b>NOTE: </b>This is another note.</p>
  </body>
</html>

and

2. JSON-to-JSON:

Fiddle: https://jsfiddle.net/YSharpLanguage/ppfmmu15/10

where this:

// (A "Company" is just an object with a "Team")
function Company(obj) {
  return obj.team && Team(obj.team);
}

// (A "Team" is just a non-empty array that contains at least one "Member")
function Team(obj) {
  return ({ }.toString.call(obj) === "[object Array]") &&
         obj.length &&
         obj.find(function(item) { return Member(item); });
}

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

function Dude(obj) {
  return Member(obj) && (obj.sex === "Male");
}

function Girl(obj) {
  return Member(obj) && (obj.sex === "Female");
}

var data = { team: [
  { first: "John", last: "Smith", sex: "Male" },
  { first: "Vaio", last: "Sony" },
  { first: "Anna", last: "Smith", sex: "Female" },
  { first: "Peter", last: "Olsen", sex: "Male" }
] };

var TO_SOMETHING_ELSE = { $: [

  [ [ Company ],
    function(company) {
      return { some_virtual_dom: {
        the_dudes: { ul: company.team.select(Dude).through(this) },
        the_grrls: { ul: company.team.select(Girl).through(this) }
      } }
    } ],

  [ [ Member ],
    function(member) {
      return { li: "{first} {last} ({sex})".of(member) };
    } ]

] };

console.log(JSON.stringify(data.through(TO_SOMETHING_ELSE), null, 4));

... gives:

{
    "some_virtual_dom": {
        "the_dudes": {
            "ul": [
                {
                    "li": "John Smith (Male)"
                },
                {
                    "li": "Peter Olsen (Male)"
                }
            ]
        },
        "the_grrls": {
            "ul": [
                {
                    "li": "Anna Smith (Female)"
                }
            ]
        }
    }
}

3. XSLT vs. JavaScript:

A JavaScript equivalent of...

XSLT 3.0 REC Section 14.4 Example: Grouping Nodes based on Common Values

(at: http://jsfiddle.net/YSharpLanguage/8bqcd0ey/1)

Cf. https://www.w3.org/TR/xslt-30/#grouping-examples

where...

var cities = [
  { name: "Milano",  country: "Italia",      pop: 5 },
  { name: "Paris",   country: "France",      pop: 7 },
  { name: "München", country: "Deutschland", pop: 4 },
  { name: "Lyon",    country: "France",      pop: 2 },
  { name: "Venezia", country: "Italia",      pop: 1 }
];

/*
  Cf.
  XSLT 3.0 REC Section 14.4
  Example: Grouping Nodes based on Common Values

  https://www.w3.org/TR/xslt-30/#grouping-examples
*/
var output = "<table>\r\n\
  <tr>\r\n\
    <th>Position</th>\r\n\
    <th>Country</th>\r\n\
    <th>City List</th>\r\n\
    <th>Population</th>\r\n\
  </tr>{*}\r\n\
</table>".of
  (
    cities.select().groupBy("country")(function(byCountry, index) {
      var country = byCountry[0],
          cities = byCountry[1].select().orderBy("name");
      return "\r\n\
  <tr>\r\n\
    <td>{position}</td>\r\n\
    <td>{country}</td>\r\n\
    <td>{cities}</td>\r\n\
    <td>{population}</td>\r\n\
  </tr>".
        of({ position: index + 1, country: country,
             cities: cities.map(function(city) { return city.name; }).join(", "),
             population: cities.reduce(function(sum, city) { return sum += city.pop; }, 0)
           });
    })
  );

... gives:

<table>
  <tr>
    <th>Position</th>
    <th>Country</th>
    <th>City List</th>
    <th>Population</th>
  </tr>
  <tr>
    <td>1</td>
    <td>Italia</td>
    <td>Milano, Venezia</td>
    <td>6</td>
  </tr>
  <tr>
    <td>2</td>
    <td>France</td>
    <td>Lyon, Paris</td>
    <td>9</td>
  </tr>
  <tr>
    <td>3</td>
    <td>Deutschland</td>
    <td>München</td>
    <td>4</td>
  </tr>
</table>

4. JSONiq vs. JavaScript:

A JavaScript equivalent of...

JSONiq Use Cases Section 1.1.2. Grouping Queries for JSON

(at: https://jsfiddle.net/YSharpLanguage/hvo24hmk/3)

Cf. http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping

where...

/*
  1.1.2. Grouping Queries for JSON
  http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping
*/
var sales = [
  { "product" : "broiler", "store number" : 1, "quantity" : 20  },
  { "product" : "toaster", "store number" : 2, "quantity" : 100 },
  { "product" : "toaster", "store number" : 2, "quantity" : 50 },
  { "product" : "toaster", "store number" : 3, "quantity" : 50 },
  { "product" : "blender", "store number" : 3, "quantity" : 100 },
  { "product" : "blender", "store number" : 3, "quantity" : 150 },
  { "product" : "socks", "store number" : 1, "quantity" : 500 },
  { "product" : "socks", "store number" : 2, "quantity" : 10 },
  { "product" : "shirt", "store number" : 3, "quantity" : 10 }
];

var products = [
  { "name" : "broiler", "category" : "kitchen", "price" : 100, "cost" : 70 },
  { "name" : "toaster", "category" : "kitchen", "price" : 30, "cost" : 10 },
  { "name" : "blender", "category" : "kitchen", "price" : 50, "cost" : 25 },
  {  "name" : "socks", "category" : "clothes", "price" : 5, "cost" : 2 },
  { "name" : "shirt", "category" : "clothes", "price" : 10, "cost" : 3 }
];

var stores = [
  { "store number" : 1, "state" : "CA" },
  { "store number" : 2, "state" : "CA" },
  { "store number" : 3, "state" : "MA" },
  { "store number" : 4, "state" : "MA" }
];

var nestedGroupingAndAggregate = stores.select().orderBy("state").groupBy("state")
( function(byState) {
    var state = byState[0],
        stateStores = byState[1];
    byState = { };
    return (
      (
        byState[state] =
        products.select().orderBy("category").groupBy("category")
        ( function(byCategory) {
            var category = byCategory[0],
                categoryProducts = byCategory[1],
                categorySales = sales.filter(function(sale) {
                  return stateStores.find(function(store) { return sale["store number"] === store["store number"]; }) &&
                         categoryProducts.find(function(product) { return sale.product === product.name; });
                });
            byCategory = { };
            return (
              (
                byCategory[category] =
                categorySales.select().orderBy("product").groupBy("product")
                ( function(byProduct) {
                    var soldProduct = byProduct[0],
                        soldQuantities = byProduct[1];
                    byProduct = { };
                    return (
                      (
                        byProduct[soldProduct] =
                        soldQuantities.reduce(function(sum, sale) { return sum += sale.quantity; }, 0)
                      ),
                      byProduct
                    );
                } ) // byProduct()
              ),
              byCategory
            );
        } ) // byCategory()
      ),
      byState
    );
} ); // byState()

... gives:

[
  {
    "CA": [
      {
        "clothes": [
          {
            "socks": 510
          }
        ]
      },
      {
        "kitchen": [
          {
            "broiler": 20
          },
          {
            "toaster": 150
          }
        ]
      }
    ]
  },
  {
    "MA": [
      {
        "clothes": [
          {
            "shirt": 10
          }
        ]
      },
      {
        "kitchen": [
          {
            "blender": 250
          },
          {
            "toaster": 50
          }
        ]
      }
    ]
  }
]

It is also useful to overcome the limitations of JSONPath wrt. querying against the ancestor axis, as raised by this SO question (and certainly others).

E.g., how to get the discount of a grocery item knowing its brand id, in

{
 "prods": [
    {
        "info": {
              "rate": 85
                },
        "grocery": [
                 {
                  "brand": "C",
                  "brand_id": "984"
                 },
                 {
                  "brand": "D",
                  "brand_id": "254"
                 }
                 ],
         "discount": "15"
    },
    {
        "info": {
              "rate": 100
                },
        "grocery": [
                 {
                  "brand": "A",
                  "brand_id": "983"
                 },
                 {
                  "brand": "B",
                  "brand_id": "253"
                 }
                 ],
         "discount": "20"
     }
 ]
}

?

A possible solution is:

var products = {
     "prods": [
        {
            "info": {
                  "rate": 85
                    },
            "grocery": [
                     {
                      "brand": "C",
                      "brand_id": "984"
                     },
                     {
                      "brand": "D",
                      "brand_id": "254"
                     }
                     ],
             "discount": "15"
        },
        {
            "info": {
                  "rate": 100
                    },
            "grocery": [
                     {
                      "brand": "A",
                      "brand_id": "983"
                     },
                     {
                      "brand": "B",
                      "brand_id": "253"
                     }
                     ],
             "discount": "20"
         }
     ]
};

function GroceryItem(obj) {
  return (typeof obj.brand === "string") && (typeof obj.brand_id === "string");
}

    // last parameter set to "true", to grab all the "GroceryItem" instances
    // at any depth:
var itemsAndDiscounts = [ products ].nodeset(GroceryItem, true).
    map(
      function(node) {
        var item = node.value, // node.value: the current "GroceryItem" (aka "$.prods[*].grocery[*]")

            discount = node.parent. // node.parent: the array of "GroceryItem" (aka "$.prods[*].grocery")
                       parent. // node.parent.parent: the product (aka "$.prods[*]")
                       discount; // node.parent.parent.discount: the product discount

        // finally, project into an easy-to-filter form:
        return { id: item.brand_id, discount: discount };
      }
    ),
    discountOfItem983;

discountOfItem983 = itemsAndDiscounts.
  filter
  (
    function(mapped) {
      return mapped.id === "983";
    }
  )
  [0].discount;

console.log("Discount of #983: " + discountOfItem983);

... which gives:

Discount of #983: 20

'HTH,

夏见 2024-08-15 08:02:32

如果说缺乏工具就意味着缺乏需求,这只是在回避问题。同样的情况也适用于 Linux 中对 X 或 Y 的支持(为什么要为如此少数的操作系统开发高质量的驱动程序和/或游戏?为什么要关注大型游戏和硬件公司不开发的操作系统?)。可能需要使用 XSLT 和 JSON 的人最终会使用一种有些微不足道的解决方法:将 JSON 转换为 XML。但这不是最佳解决方案,不是吗?

当您拥有本机 JSON 格式并且想要在浏览器中“所见即所得”编辑它时,XSLT 将是解决该问题的充分解决方案。使用传统的 JavaScript 编程来做到这一点可能会变得很痛苦。

事实上,我已经实现了 XSLT 的“石器时代”方法,使用子字符串解析来解释 javascript 的一些基本命令,例如调用模板、处理子级等。当然,使用 JSON 对象实现转换引擎比实现一个成熟的 XML 解析器来解析 XSLT。问题是,要使用 XML 模板转换 JSON 对象,您需要解析模板的 XML。

要使用 XML(或 HTML、文本或其他内容)转换 JSON 对象,您需要仔细考虑语法以及需要使用哪些特殊字符来标识转换命令。否则,您最终将不得不为您自己的自定义模板语言设计一个解析器。走过那条路之后,我可以告诉你,这条路并不美好。

更新(2010 年 11 月 12 日):经过几周的解析器工作,我已经能够对其进行优化。预先解析模板并将命令存储为 JSON 对象。转换规则也是 JSON 对象,而模板代码是 HTML 和类似于 shell 代码的自制语法的混合。我已经能够将复杂的 JSON 文档转换为 HTML 来制作文档编辑器。编辑器代码约为 1K 行(这是一个私人项目,所以我无法共享),JSON 转换代码约为 990 行(包括迭代命令、简单比较、模板调用、变量保存和评估)。我计划在麻省理工学院的许可下发布它。如果您想参与,请给我发邮件。

To say lack of tools suggest lack of need is just begging the question. The same could be applied to support for X or Y in Linux (Why bother developing quality drivers and/or games for such a minority OS? And why pay attention to an OS that big game and hardware companies don't develop for?). Probably the people who would need to use XSLT and JSON end up using a somewhat trivial workaround: Transforming JSON into XML. But that's not the optimal solution, is it?

When you have a native JSON format and you want to edit it "wysywyg" in the browser, XSLT would be a more than adequate solution for the problem. Doing that with traditional javascript programming can become a pain in the arse.

In fact, I have implemented a "stone-age" approach to XSLT, using substring parsing to interpret some basic commands for javascript, like calling a template, process children, etc. Certainly implementing a transformation engine with a JSON object is much easier than implementing a full-fledged XML parser to parse the XSLT. Problem is, that to use XML templates to transform a JSON object you need to parse the XML of the templates.

To tranform a JSON object with XML (or HTML, or text or whatever) you need to think carefully about the syntax and what special characters you need to use to identify the transformation commands. Otherwise you'll end up having to design a parser for your own custom templating language. Having walked through that path, I can tell you that it's not pretty.

Update (Nov 12, 2010): After a couple of weeks working on my parser, I've been able to optimize it. Templates are parsed beforehand and commands are stored as JSON objects. Transformation rules are also JSON objects, while the template code is a mix of HTML and a homebrew syntax similar to shell code. I've been able to transform a complex JSON document into HTML to make a document editor. The code is around 1K lines for the editor (it's for a private project so I can't share it) and around 990 lines for the JSON transformation code (includes iteration commands, simple comparisons, template calling, variable saving and evaluation). I plan to release it under a MIT license. Drop me a mail if you want to get involved.

嘿哥们儿 2024-08-15 08:02:32

作为老问题的另一个新答案,我建议看看 DefiantJS。它不是 JSON 的 XSLT 等价物,它 JSON 的 XSLT。文档的“模板”部分包括以下示例:

<!-- Defiant template -->
<script type="defiant/xsl-template">
    <xsl:template name="books_template">
        <xsl:for-each select="//movie">
            <xsl:value-of select="title"/><br/>
        </xsl:for-each>
    </xsl:template>
</script>

<script type="text/javascript">

var data = {
        "movie": [
            {"title": "The Usual Suspects"},
            {"title": "Pulp Fiction"},
            {"title": "Independence Day"}
        ]
    },
    htm = Defiant.render('books_template', data);

console.log(htm);
// The Usual Suspects<br>
// Pulp Fiction<br>
// Independence Day<br>

As yet another new answer to an old question, I'd suggest a look at DefiantJS. It's not an XSLT equivalent for JSON, it is XSLT for JSON. The "Templating" section of the documentation includes this example:

<!-- Defiant template -->
<script type="defiant/xsl-template">
    <xsl:template name="books_template">
        <xsl:for-each select="//movie">
            <xsl:value-of select="title"/><br/>
        </xsl:for-each>
    </xsl:template>
</script>

<script type="text/javascript">

var data = {
        "movie": [
            {"title": "The Usual Suspects"},
            {"title": "Pulp Fiction"},
            {"title": "Independence Day"}
        ]
    },
    htm = Defiant.render('books_template', data);

console.log(htm);
// The Usual Suspects<br>
// Pulp Fiction<br>
// Independence Day<br>
记忆で 2024-08-15 08:02:32

现在有了!我最近创建了一个库,json-transforms,正是为了这个目的:

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

它使用 DSL 的组合 JSPath以 XPath 为模型,以及直接受 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 }
  ]
}

该转换由三个规则组成。第一个匹配本田制造的任何汽车,发出具有本田属性的对象,然后递归匹配。第二条规则匹配具有 maker 属性的任何对象,输出 modelyear 属性。最后是递归匹配的恒等变换。

There is now! I recently created a library, json-transforms, exactly for this purpose:

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

It uses a combination of JSPath, a DSL modelled on XPath, and a recursive pattern matching approach, inspired directly by XSLT.

Here's a quick example. Given the following JSON object:

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

Here's a transformation:

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

Which output the following:

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

This transform is composed of three rules. The first matches any automobile which is made by Honda, emitting an object with a Honda property, then recursively matching. The second rule matches any object with a maker property, outputting the model and year properties. The final is the identity transform that recursively matches.

や三分注定 2024-08-15 08:02:32

我真的厌倦了大量的 JavaScript 模板引擎,以及它们所有的内联 HTML 模板、不同的标记样式等,并决定 构建一个小型库,支持 JSON 数据结构的 XSLT 格式。无论如何,这都不是火箭科学——它只是将 JSON 解析为 XML,然后使用 XSLT 文档进行格式化。它也很快,虽然不如 Chrome 中的 JavaScript 模板引擎快,但在大多数其他浏览器中,它至少与大型数据结构的 JS 引擎替代品一样快。

I've been really tired of the enormous amount of JavaScript templating engines out there, and all their inline HTML-templates, different markup styles, etc., and decided to build a small library that enables XSLT formatting for JSON data structures. Not rocket science in any way -- it's just JSON parsed to XML and then formatted with a XSLT document. It's fast too, not as fast as JavaScript template engines in Chrome, but in most other browsers it's at least as fast as the JS engine alternative for larger data structures.

几度春秋 2024-08-15 08:02:32

我正在使用 Camel 路线 umashal(xmljson) ->到(xlst)->元帅(xmljson)。足够高效(虽然不是 100% 完美),但很简单,如果您已经在使用 Camel。

I am using Camel route umarshal(xmljson) -> to(xlst) -> marshal(xmljson). Efficient enough (though not 100% perfect), but simple, if you are already using Camel.

心意如水 2024-08-15 08:02:32

JSLT 非常接近 XSLT 的 JSON 等效项。它是一种转换语言,您可以使用 JSON 语法编写输出的固定部分,然后插入表达式来计算要插入模板中的值。

一个例子:

{
  "time": round(parse-time(.published, "yyyy-MM-dd'T'HH:mm:ssX") * 1000),
  "device_manufacturer": .device.manufacturer,
  "device_model": .device.model,
  "language": .device.acceptLanguage
}

它是在 Jackson 之上用 Java 实现的。

JSLT is very close to a JSON equivalent of XSLT. It's a transform language where you write the fixed part of the output in JSON syntax, then insert expressions to compute the values you want to insert in the template.

An example:

{
  "time": round(parse-time(.published, "yyyy-MM-dd'T'HH:mm:ssX") * 1000),
  "device_manufacturer": .device.manufacturer,
  "device_model": .device.model,
  "language": .device.acceptLanguage
}

It's implemented in Java on top of Jackson.

思念绕指尖 2024-08-15 08:02:32

JSONiq 就是这样一个标准,Zorba 开源 C++ 实现。 JSONiq 也可以被视为添加 JSON 作为本机数据类型的 XQuery。

JSONiq is such a standard and Zorba an open-source C++ implementation. JSONiq can also be seen as XQuery with adding JSON as a native data type.

我做我的改变 2024-08-15 08:02:32

很可能使用 XSLT 转换 JSON:您需要 JSON2SAX 反序列化器和 SAX2JSON 序列化器。

Java 中的示例代码:
http://www.gerixsoft.com/blog/json/xslt4json

it is very possible to convert JSON using XSLT: you need JSON2SAX deserializer and SAX2JSON serializer.

Sample code in Java:
http://www.gerixsoft.com/blog/json/xslt4json

高跟鞋的旋律 2024-08-15 08:02:32

Yate (https://github.com/pasaran/yate) 是在 XSLT 之后专门设计的,具有 JPath 特性(JS 的自然 XPath 等效项),编译为 JavaScript,并且具有相当长的生产使用历史。它实际上没有记录,但阅读示例和测试应该足够了。

Yate (https://github.com/pasaran/yate) is specifically designed after XSLT, features JPath (a natural XPath equivalent for JS), compiles to JavaScript and has quite a history of production use. It’s practically undocumented, but reading through samples and tests should be enough.

花桑 2024-08-15 08:02:32

我知道这是一篇旧帖子,但我刚刚遇到它,尽管我有偏见,因为我最初编写了该工具,但我认为我有最适合该问题的答案。

该语言、DTL 或数据转换语言是专门为转换 JSON(或任何结构化数据)而设计的。它的用途与 XSLT 非常相似,您可以在 npm 上以 dtl-js 形式或在网站 getdtl.org 上找到它其中包括一个实时浏览器内工具来探索它。

看起来像这样:

{ 
  "out": { 
    "id": "(: $user_id :)", 
    "personalInfo": { 
      "name": "(: &( $first_name ' ' $last_name ) :)", 
      "age": "(: $age :)" 
    }, 
    "contactDetails": { 
      "email": "(: $email :)", 
      "phone": "(: $phone :)" 
    }, 
    "address": { 
      "street": "(: $address1 :)", 
      "unit": "(: $address2 :)", 
      "city": "(: $addr_city :)", 
      "postal_code": "(: $addr_zip :)" 
    } 
  } 
}

DTL 和 XSLT 在几个重要方面是相似的:

  1. 数据转换的目的:XSLT 和 DTL 主要用于转换数据。它们获取输入数据并将其转换为所需的输出格式。

  2. 支持复杂转换:两者都可以处理复杂的数据转换,允许用户以复杂的方式操作和重组数据。

  3. 嵌入性:两者都可以嵌入到它们转换的数据中。 DTL 可以嵌入到 JSON 结构中,就像 XML 文件中的 XSLT 一样。

  4. 基于规则的逻辑:它们根据定义的规则或模式进行操作 - XSLT 对 XML 元素使用模板规则,而 DTL 对 JSON 元素使用转换表达式。

  5. 模式匹配:XSLT 使用 XPath 来选择 XML 节点,类似地,DTL 使用表达式根据特定条件选择和操作 JSON 元素。

  6. 声明性:两种语言都是声明性的,重点关注转换应该实现什么而不是如何完成。

  7. 迭代和条件处理:它们支持条件逻辑和迭代 - XSLT,具有 xsl:for-eachxsl:if 等结构,以及带有 mapgrep 等帮助器的 DTL。

  8. 可扩展性:两者都可以通过附加功能进行扩展,例如 XSLT 中的自定义函数和 DTL 中的自定义帮助程序。

  9. 转换上下文感知:每个都有一个上下文感知转换过程,这对于将正确的转换逻辑应用于数据至关重要。

  10. 数据不可知逻辑:两者中的转换逻辑都是数据不可知的,允许其应用于符合预期结构的不同数据集。

简而言之,DTL 是为 JSON 量身定制的,专门设计用于对 JSON 执行与 XSLT 对 XML 执行的完全相同的工作。

再说一次,我有偏见,但 DTL 与 XSLT 不同的一些重要方面:

  1. 更容易理解
    DTL 转换结构通常反映所需的输出结构,并且语法更易于理解和阅读。 (您可以查看快速入门,它告诉您需要了解的所有信息。 )

  2. 数据格式灵活性
    虽然 DTL 主要是为 JSON 设计的,但它也可以处理 YAML、CSV,甚至纯文本数据。这种多功能性使得 DTL 更适合 XML 之外的各种数据格式。 dtl 命令行工具可使用多种格式进行批量数据处理。

  3. 与现代网络技术集成
    DTL 与 JavaScript 和现代 Web 开发实践无缝集成,使其非常适合主要使用 JSON 的 Web 应用程序。它运行在服务器上、浏览器中,甚至直接用于 MongoDB 等 NoSQL 数据库。

  4. 易于调试
    DTL 更简单的语法和结构可以使调试更容易,尤其是在 JavaScript 环境中使用时。 网站上的交互式工具和 dtlr 命令行 REPL/数据浏览器让一切变得简单弄清楚你需要做什么。

  5. 可读性和维护
    DTL 简单的语法和类似 JSON 的结构可以使 DTL 转换更具可读性和可维护性。

  6. 强大的编辑器支持
    DTL 具有强大的编辑器支持,为 vs-code、sublime-text 和 vim 中的所有内置功能提供语法突出显示和片段。

再说一次,我最初写它是因为我有偏见,但我写它是因为这个问题没有一个好的答案。它很稳定且易于维护,自 2013 年以来已被许多公司投入生产使用,而且它的功能非常出色。

希望有帮助。

I know this is an old post, but I just came across it and, though I'm biased because I wrote the tool originally, I think I have the answer that most fits the question.

The language, DTL, or Data Transformation Language is specifically designed for transforming JSON (or any structured data). It is very similar in purpose to XSLT You can find it on npm as dtl-js or on the website getdtl.org which includes a live in-browser tool to explore it.

It looks like this:

{ 
  "out": { 
    "id": "(: $user_id :)", 
    "personalInfo": { 
      "name": "(: &( $first_name ' ' $last_name ) :)", 
      "age": "(: $age :)" 
    }, 
    "contactDetails": { 
      "email": "(: $email :)", 
      "phone": "(: $phone :)" 
    }, 
    "address": { 
      "street": "(: $address1 :)", 
      "unit": "(: $address2 :)", 
      "city": "(: $addr_city :)", 
      "postal_code": "(: $addr_zip :)" 
    } 
  } 
}

DTL and XSLT are alike in several important ways:

  1. Purpose for Data Transformation: Both XSLT and DTL are primarily used for transforming data. They take input data and transform it into a desired output format.

  2. Support for Complex Transformations: Both can handle complex data transformations, allowing users to manipulate and restructure data in sophisticated ways.

  3. Embeddability: Both can be embedded within the data they transform. DTL can be embedded within JSON structures, much like XSLT within XML files.

  4. Rule-Based Logic: They operate based on defined rules or patterns - XSLT uses template rules for XML elements, whereas DTL uses transformation expressions for JSON elements.

  5. Pattern Matching: XSLT utilizes XPath for selecting XML nodes, and similarly, DTL employs expressions to select and manipulate JSON elements based on certain criteria.

  6. Declarative Nature: Both languages are declarative, focusing on what the transformation should achieve rather than how it should be done.

  7. Iterative and Conditional Processing: They support conditional logic and iteration - XSLT with constructs like xsl:for-each and xsl:if, and DTL with helpers like map and grep.

  8. Extensibility: Both can be extended with additional functionalities, like custom functions in XSLT and custom helpers in DTL.

  9. Transformation Context Awareness: Each has a context-aware transformation process, essential for applying the correct transformation logic to the data.

  10. Data Agnostic Logic: The transformation logic in both is data-agnostic, allowing it to be applied to different sets of data that conform to the expected structure.

In short, DTL is tailored for JSON and is specifically designed to do exactly the same job for JSON that XSLT does for XML.

Again, I'm biased, but some important ways DTL is different from XSLT:

  1. Easier to Understand:
    DTL transform structure usually mirrors the desired output structure and the syntax is much simpler to understand and read. (You can look at the quickstart which tells you everything you need to know.)

  2. Data Format Flexibility:
    While DTL is primarily designed for JSON, it can also handle YAML, CSV, and even plain text data. This versatility makes DTL more suitable for a variety of data formats beyond XML. The dtl command line tool works with multiple formats for bulk data processing.

  3. Integration with Modern Web Technologies:
    DTL integrates seamlessly with JavaScript and modern web development practices, making it a natural fit for web applications that predominantly use JSON. It runs on the server, in the browser, and has even been used directly in NoSQL databases like MongoDB.

  4. Ease of Debugging:
    The simpler syntax and structure of DTL can make debugging easier, especially when used within JavaScript environments. The interactive tool on the website and the dtlr command line REPL / data explorer make it easy to figure out what you need to do.

  5. Readability and Maintenance:
    DTL's straightforward syntax and JSON-like structure can make DTL transformations more readable and maintainable.

  6. Strong editor support:
    DTL has strong editor support, providing syntax highlighting and snippets for all built-in functionality in vs-code, sublime-text and vim.

Again, I wrote it originally so I'm biased, but I wrote it because there wasn't a good answer for this question. It's stable and maintained and it's been in production use since 2013 by many companies and it's very good at what it does.

Hope it helps.

挖鼻大婶 2024-08-15 08:02:32

为什么不使用 Mr. 将 JSON 转换为 XML Data Coverter,使用 XSLT 将其转换,然后使用相同的方法将其更改回 JSON。

Why don't you converts JSON to XML using Mr. Data Coverter , tranform it using XSLT and then change it back to JSON using the same.

2024-08-15 08:02:32

有关利用纯 JavaScript 以及 XSLT 匹配表达式和递归模板背后熟悉的声明性模式的方法的工作涂鸦/概念证明,请参阅 https://gist.github.com/brettz9/0e661b3093764f496e36

(对于 JSON 可能采取类似的方法。)

请注意,该演示还依赖于 JavaScript 1.8 表达式闭包,以便于表达模板在 Firefox 中(至少在方法的 ES6 缩写形式可能实现之前)。

免责声明:这是我自己的代码。

For a working doodle/proof of concept of an approach to utilize pure JavaScript along with the familiar and declarative pattern behind XSLT's matching expressions and recursive templates, see https://gist.github.com/brettz9/0e661b3093764f496e36

(A similar approach might be taken for JSON.)

Note that the demo also relies on JavaScript 1.8 expression closures for convenience in expressing templates in Firefox (at least until the ES6 short form for methods may be implemented).

Disclaimer: This is my own code.

垂暮老矣 2024-08-15 08:02:32

很久以前,我为我的基于 Jackson 的 json 处理框架编写了一个 dom 适配器。它使用 nu.xom 库。生成的 dom 树与 java xpath 和 xslt 工具一起使用。我做出了一些非常简单的实现选择。例如,根节点始终称为“root”,数组进入带有 li 子元素的 ol 节点(如在 html 中),其他所有内容都只是具有原始值的子节点或另一个对象节点。

JsonXmlConverter.java< /a>

用法:
<代码>
JsonObject 样本Json = 样本Json();
org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson, "root");

I wrote a dom adapter for my jackson based json processing framework long time ago. It uses the nu.xom library. The resulting dom tree works with the java xpath and xslt facilities. I made some implementation choices that are pretty straightforward. For example the root node is always called "root", arrays go into an ol node with li sub elements (like in html), and everything else is just a sub node with a primitive value or another object node.

JsonXmlConverter.java

Usage:

JsonObject sampleJson = sampleJson();
org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson, "root");

尛丟丟 2024-08-15 08:02:32

尚未给出的一种方法是使用解析器生成器在 XSLT 中创建解析器,该解析器解析 JSON 并生成 XML 输出。

在 XML 会议上经常提到的一个选项是 ReX 解析器生成器 (http://www.bottlecaps. de/rex/) - 尽管网站上完全没有记录,但可以通过搜索找到菜谱。

One approach not yet given is to use a parser generator to create a parser in XSLT which parses JSON and produces an XML output.

One option that gets mentioned a lot at the XML conferences is the ReX parser generator (http://www.bottlecaps.de/rex/) - although totally undocumented on the site, recipes are available on searching.

吝吻 2024-08-15 08:02:32

可以将 XSLT 与 JSON 结合使用。
XPath(3.1) XSLT(3.0) 和 XQuery(3.1) 的版本 3 以某种方式支持 JSON。
这似乎在 Saxon 的商业版本中可用,并且可能在某个时候包含在 HE 版本中。
https://www.saxonica.com/html/documentation/ functions/fn/parse-json.html

-

我对替代解决方案的期望:

我希望能够输入 JSON 来获取匹配的数据集,并输出 JSON 或文本。

访问任意属性并评估值

支持条件逻辑

我希望转换脚本位于工具外部、基于文本,并且最好是常用语言。

潜在的替代方案?

我想知道 SQL 是否是一个合适的替代方案。
https://learn.microsoft。 com/en-us/sql/relational-databases/json/json-data-sql-server

如果替代工具可以处理 JSON 和 XML 那就太好了
https://learn.microsoft.com/ en-us/sql/relational-databases/xml/openxml-sql-server

我还没有尝试将我使用的 XSLT 脚本转换为 SQL,也没有完全评估此选项,但我希望研究一下很快就会有更多。到目前为止只是一些想法。

It may be possible to use XSLT with JSON.
Verson 3 of XPath(3.1) XSLT(3.0) and XQuery(3.1) supports JSON in some way.
This seems to be available in the commercial version of Saxon, and might at some point be included in the HE version.
https://www.saxonica.com/html/documentation/functions/fn/parse-json.html

-

What I would expect from an alternative solution:

I would want to be able input JSON to fetch a matching set of data, and output JSON or TEXT.

Access arbitrary properties and evaluate the values

Support for conditional logic

I would want the transformation scripts to be external from the tool, text based, and preferably a commonly used language.

Potential alternative?

I wonder if SQL could be a suitable alternative.
https://learn.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

It would be nice if the alternative tool could handle JSON and XML
https://learn.microsoft.com/en-us/sql/relational-databases/xml/openxml-sql-server

I have not yet tried to convert the XSLT scripts I use to SQL, or fully evaluated this option yet, but I hope to look into it more soon. Just some thoughts so far.

冷…雨湿花 2024-08-15 08:02:32

CsvCruncher

尽管它的名字没有暗示,CsvCruncher 可以有效地用于读取表格* JSON 数据并使用 SQL 处理它们。

* 表格表示 JSON 树的某些部分是规则的,即具有相同或相似结构的一对多条目。

CsvCruncher 将树的这一部分转换为 SQL 表,然后您就有完整的 SQL 语法来查询它。
您还可以加载多个 JSON 树,然后使用多个表。
您还可以将 SQL 结果存储为 JSON(或 CSV),然后再次处理。

这比真正复杂的 XSLT 方法更适合我(尽管当您真正深入了解它时它会很有趣)。

免责声明:我是 CsvCruncher 的开发者。

CsvCruncher

Despite it's name does not suggest it, CsvCruncher can be efficiently used to read tabular* JSON data and process them using SQL.

* Tabular means that some part of the JSON tree is regular, i.e. one to many entries of same or similar structure.

CsvCruncher turns this part of the tree into a SQL table, and then you have a full SQL syntax to query it.
You may also load multiple JSON trees, and then have multiple tables to play with.
You may also store the SQL result as a JSON (or CSV) and then process it again.

This has served me way better than really complicated XSLT approach (despite it's a lot of fun when you really know it deeply).

Disclaimer: I am the developer of CsvCruncher.

暖阳 2024-08-15 08:02:32

不太确定是否需要这样做,对我来说,缺乏工具就意味着缺乏需要。 JSON 最好作为对象进行处理(无论如何,它在 JS 中的处理方式),并且您通常使用对象本身的语言来进行转换(Java 用于从 JSON 创建的 Java 对象,同样适用于 Perl、Python、Perl、c#、PHP 等在)。只需进行正常的赋值(或设置、获取)、循环等即可。

我的意思是,XSLT 只是另一种语言,需要它的一个原因是 XML 不是对象表示法,因此编程语言的对象并不完全适合(分层 xml 模型和对象/结构之间的阻抗)。

Not too sure there is need for this, and to me lack of tools suggests lack of need. JSON is best processed as objects (the way it's done in JS anyway), and you typically use language of the objects itself to do transformations (Java for Java objects created from JSON, same for Perl, Python, Perl, c#, PHP and so on). Just with normal assignments (or set, get), looping and so on.

I mean, XSLT is just another language, and one reason it is needed is that XML is not an object notation and thus objects of programming languages are not exact fits (impedance between hierarchic xml model and objects/structs).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文