JSON 的 XSLT 等效项
-
06-07-2019 - |
题
有没有一个 XSLT 相当于 JSON?允许我对 JSON 进行转换,就像 XSLT 对 XML 所做的那样。
解决方案
有趣的想法。在 Google 上进行的一些搜索产生了一些感兴趣的页面,包括:
- 一个 大纲 如何实现这样的“jsonT”工具,以及 一些下载
- 一些 对该实施方案的讨论
- 一家公司 可能已经实施了一些合适的东西
希望这可以帮助。
其他提示
尝试 JOLT 。它是用Java编写的JSON to JSON转换库。
它是专门创建的,因为我们不想播放“JSON - > XML - > XSLT - > XML - > JSON"游戏,并使用模板进行任何足够复杂的转换是不可维护的。
JSON 的 XSLT 等效项 - 候选列表(工具和规范)
工具
- XSLT
您可以使用 JSON 的 XSLT 目的是 fn:json 转 xml.
本节介绍允许使用 XSLT 处理 JSON 数据的工具。
- 杰克
jq 就像 JSON 数据的 sed - 您可以使用它来切片、过滤、映射和转换结构化数据,就像 sed、awk、grep 和朋友让您处理文本一样轻松。有针对不同操作系统的安装包。
- 杰杰
JJ 是一个命令行实用程序,它提供了一种快速而简单的方法来检索或更新 JSON 文档中的值。它的底层由 GJSON 和 SJSON 提供支持。
- FX
命令行 JSON 处理工具
- 不需要学习新语法
- 纯 JavaScript
- 格式化和突出显示
- 独立二进制文件
- 杰尔
jl(“JSON lambda”)是一种用于查询和操作 JSON 的小型函数式语言。
- 颠簸
用 Java 编写的 JSON 到 JSON 转换库,其中转换的“规范”本身就是一个 JSON 文档。
- 格罗恩
使 JSON 可 grep 化!gron 将 JSON 转换为离散分配,以便更轻松地 grep 查找您想要的内容并查看它的绝对“路径”。它简化了对返回大量 JSON 但文档很糟糕的 API 的探索。
- json
json 是一个用于处理 JSON 的快速 CLI 工具。它是一个单文件 Node.js 脚本,没有外部依赖(除了 Node.js 本身)。
- json-e
JSON-e 是一种数据结构参数化系统,用于在 JSON 对象中嵌入上下文。中心思想是将数据结构视为“模板”,并使用另一个数据结构作为上下文对其进行转换,以生成输出数据结构。
- JSLT
JSLT 是一种完整的 JSON 查询和转换语言。语言设计的灵感来自于 jq、XPath 和 XQuery。
- json 转换 最后提交时间:2017 年 12 月 1 日
提供递归、模式匹配方法来转换 JSON 数据。转换被定义为与 JSON 对象的结构相匹配的一组规则。当发生匹配时,规则会发出转换后的数据,并可选择递归以转换子对象。
- 杰索克 最后提交时间:2015 年 3 月 4 日
Jsawk 类似于 awk,但用于 JSON。您使用从 stdin 读取的 JSON 对象数组,使用 JavaScript 过滤它们以生成打印到 stdout 的结果数组。
- 亚特 最后提交时间:2017 年 3 月 13 日
- jsonpath-对象转换 最后提交时间:2017 年 1 月 18 日
使用 JSONPath 从对象文本中提取数据并基于模板生成新对象。
- 装订 最后提交时间:2013 年 9 月 16 日
Stapling 是一个 JavaScript 库,支持 JSON 对象的 XSLT 格式设置。Stapling 不使用 JavaScript 模板引擎和 text/html 模板,而是让您有机会使用 XSLT 模板(通过 Ajax 异步加载,然后缓存客户端)来解析 JSON 数据源。
眼镜:
XSLT支持JSON,如 http://www.w3.org/TR所示/ XSLT-30 /#JSON
XML使用尖括号作为分隔符标记,JSON使用大括号,方括号,...... I. e。 XML更少的令牌识别比较意味着它针对声明性转换进行了优化,而更多的比较,如switch语句,出于速度原因,假设推测分支预测脚本语言中的命令性代码是有用的。直接结果是,对于半结构化数据的不同组合,您可能希望将XSLT和javascript引擎的性能作为响应式页面的一部分进行基准测试。对于可忽略的数据有效负载,转换可能与没有XML序列化的JSON一样好。 W3的决定应该基于更好的分析。
我最近找到了一个我喜欢的JSON样式工具: https://github.com/twigkit/tempo 。非常简单的工具 - 在我看来,它比XSLT更容易使用 - 不需要XPATH查询。
它不像XSLT那样基于模板,但更简洁。例如将 name
和 address
字段提取到数组中: [.name,.address]
说缺乏工具表明缺乏需求只是乞求这个问题。同样可以用于支持Linux中的X或Y(为什么要为这样的少数操作系统开发高质量的驱动程序和/或游戏?为什么要关注大型游戏和硬件公司不开发的操作系统?)。可能需要使用XSLT和JSON的人最终会使用一些简单的解决方法:将JSON转换为XML。但这不是最佳解决方案,是吗?
当您使用原生JSON格式并且想要编辑它时,“wysywyg”在浏览器中,XSLT将成为解决问题的绰绰有余的解决方案。使用传统的javascript编程实现这一点可能会成为一种痛苦。
事实上,我已经实施了“石器时代”。处理XSLT,使用子字符串解析来解释javascript的一些基本命令,比如调用模板,处理子进程等。当然,实现带有JSON对象的转换引擎要比实现完整的XML解析器来解析XSLT容易得多。问题是,要使用XML模板转换JSON对象,需要解析模板的XML。
要使用XML(或HTML,或文本或其他)转换JSON对象,您需要仔细考虑语法以及需要使用哪些特殊字符来标识转换命令。否则,您最终将不得不为自己的自定义模板语言设计解析器。走过这条路,我可以告诉你它并不漂亮。
更新(2010年11月12日):经过几周的解析器工作,我已经能够对其进行优化。事先解析模板,并将命令存储为JSON对象。转换规则也是JSON对象,而模板代码是HTML和类似于shell代码的自制语法的混合。我已经能够将复杂的JSON文档转换为HTML以制作文档编辑器。代码大约是1K行的编辑器(它是私有项目所以我不能共享它)和大约990行的JSON转换代码(包括迭代命令,简单比较,模板调用,变量保存和评估)。我计划在MIT许可下发布它。如果你想参与,请给我发邮件。
我最近在这周围编写了自己的小型图书馆,试图保持与
的接近5.1处理模型(XSLT REC) https://www.w3.org/TR/xslt#section-Processing-Model
尽可能(尽我所能),用几行JavaScript代码。
以下是一些使用不太完全无关的例子......
1。 JSON到一些的标记:
小提琴: 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节示例:根据公共值对节点进行分组
(at: 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:
相当于......的JavaScript
(at: https://jsfiddle.net/YSharpLanguage/hvo24hmk/3 )
比照 http://jsoniq.org/docs/JSONiq-usecases/html - 单/ 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,
现在有!我最近创建了一个库 json-transforms ,正是为了这个目的:
https://github.com/ColinEberhardt/json-transforms
它结合使用 JSPath ,以XPath为模型的DSL,以及递归模式匹配方法,灵感来自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
属性的对象,然后递归匹配。第二个规则将任何对象与 maker
属性匹配,输出 model
和 year
属性。最后是递归匹配的身份转换。
作为旧问题的另一个新答案,我建议您查看 DefiantJS 。它不是JSON的XSLT 等效, 是 XSLT for JSON。 “模板化”文档的一部分包括这个例子:
<!-- 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>
我已经厌倦了大量的JavaScript模板引擎,以及所有内联HTML模板,不同的标记样式等,并决定构建一个小型库,为JSON数据结构启用XSLT格式化。这不是火箭科学 - 它只是将JSON解析为XML,然后使用XSLT文档进行格式化。它也很快,不像Chrome中的JavaScript模板引擎那么快,但在大多数其他浏览器中,它至少与大型数据结构的JS引擎替代方案一样快。
我正在使用Camel route unmarshal(xml json) - &gt;到(xslt) - &gt;编组(xmljson)。足够高效(虽然不是100%完美),但很简单,如果你已经在使用Camel。
使用XSLT转换JSON是非常有可能的:您需要JSON2SAX反序列化器和SAX2JSON序列化器。
Java中的示例代码: http://www.gerixsoft.com/blog/json/xslt4json
Yate( https://github.com/pasaran/yate )是专门为XSLT设计的,具有JPath(与JS相当的自然XPath),编译为JavaScript并具有相当的生产历史。它实际上没有记录,但阅读样本和测试应该足够了。
JSLT 非常接近JSL等效的XSLT。它是一种转换语言,您可以使用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
}
它是在杰克逊的Java上实现的。
不太确定是否需要这个,而对我来说,缺乏工具表明缺乏需求。 JSON最好作为对象处理(无论如何都是在JS中完成的),并且您通常使用对象本身的语言来进行转换(Java用于从JSON创建的Java对象,对于Perl,Python,Perl,c#,PHP等都是如此)上)。只需正常分配(或设置,获取),循环等等。
我的意思是,XSLT只是另一种语言,需要的一个原因是XML不是对象符号,因此编程语言的对象不是精确匹配(分层xml模型和对象/结构之间的阻抗)。 p>
为什么不使用 Mr.将JSON转换为XML数据转换器,使用XSLT对其进行转换,然后使用相同的方法将其更改回JSON。
对于使用纯JavaScript以及XSLT匹配表达式和递归模板背后的熟悉和声明模式的方法的工作涂鸦/概念证明,请参阅 https://gist.github.com/brettz9/0e661b3093764f496e36
(JSON可能采用类似的方法。)
请注意,该演示还依赖于JavaScript 1.8表达式闭包,以方便在Firefox中表达模板(至少在可以实现方法的ES6简写形式之前)。
免责声明:这是我自己的代码。
我很久以前就为基于jackson的json处理框架编写了一个dom适配器。它使用nu.xom库。生成的dom树与java xpath和xslt工具一起使用。我做了一些非常简单的实现选择。例如,根节点总是被称为“root”,数组进入具有li子元素的ol节点(如html中),而其他所有内容只是具有原始值的子节点或另一个对象节点。
使用方法: <代码> JsonObject sampleJson = sampleJson(); org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson,&quot; root&quot;); 代码>
尚未给出的一种方法是使用解析器生成器在XSLT中创建解析器,该解析器解析JSON并生成XML输出。
在XML会议上经常提到的一个选项是ReX解析器生成器( http:// www .bottlecaps.de / rex / ) - 虽然在网站上完全没有记录,但搜索时可以使用食谱。
可以将XSLT与JSON一起使用。 XPath(3.1)的第3版XSLT(3.0)和XQuery(3.1)以某种方式支持JSON。 这似乎可以在Saxon的商业版本中获得,并且可能在某些时候包含在HE版本中。 https://www.saxonica.com/html/documentation/功能/ FN /解析-json.html
-
我对替代解决方案的期望是什么:
我希望能够输入JSON来获取匹配的数据集,并输出JSON或TEXT。
访问任意属性并评估值
支持条件逻辑
我希望转换脚本来自工具,基于文本,最好是常用的语言。
潜在的替代方案?
我想知道SQL是否是一个合适的选择。 https://docs.microsoft。 COM / EN-US / SQL /关系的数据库/ JSON / JSON-数据-SQL服务器
如果替代工具可以处理JSON和XML,那将是很好的 https://docs.microsoft.com/ EN-US / SQL /关系的数据库/ XML / OPENXML-SQL服务器
我还没有尝试将我使用的XSLT脚本转换为SQL,或者尚未完全评估此选项,但我希望能够更快地进行调查。到目前为止只是一些想法。
JSON-e 在Node.js,Python和Go中实现。