JSON是否有等价的XSLT ?它允许我对JSON进行转换,就像XSLT对XML所做的那样。
当前回答
很久以前,我为我的基于jackson的json处理框架写了一个dom适配器。它用了。xom图书馆。生成的dom树可以使用java xpath和xslt工具。我做了一些非常简单的实现选择。例如,根节点总是被称为“root”,数组进入一个带有li子元素的ol节点(就像在html中一样),而其他一切都只是一个带有原始值或另一个对象节点的子节点。
JsonXmlConverter.java
用法: JsonObject sampleJson = sampleJson(); org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson, “root”);
其他回答
JSONiq就是这样一个标准,而Zorba是一个开源的c++实现。JSONiq也可以看作是添加了JSON作为原生数据类型的XQuery。
有关利用纯JavaScript的方法以及XSLT匹配表达式和递归模板背后熟悉的声明式模式的工作演示/概念证明,请参见https://gist.github.com/brettz9/0e661b3093764f496e36
(JSON也可以采用类似的方法。)
注意,为了方便在Firefox中表达模板,演示还依赖于JavaScript 1.8表达式闭包(至少在实现方法的ES6简写形式之前是如此)。
免责声明:这是我自己的代码。
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.
最近,我围绕着这个写了自己的小库,尽量保持接近
5.1处理模型(XSLT REC) https://www.w3.org/TR/xslt#section-Processing-Model
在几行JavaScript代码中。
这里有一些不完全琐碎的使用示例……
1. JSON-to-some-markup:
小提琴: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>
and
2. JSON-to-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 vs. JavaScript:
JavaScript等价于…
JSONiq用例1.1.2节。JSON查询分组
(https://jsfiddle.net/YSharpLanguage/hvo24hmk/3)
参看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问题(当然还有其他问题)所提出的那样。
例如,如何获得折扣的杂货项目知道其品牌标识,在
{
"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,
为什么不使用Mr. Data Coverter将JSON转换为XML,然后使用XSLT将其转换为JSON呢?
推荐文章
- 从JSON生成Java类?
- 使用Jackson将Java对象转换为JSON
- Javascript对象Vs JSON
- 在Swift中将字典转换为JSON
- 如何使用新的PostgreSQL JSON数据类型中的字段进行查询?
- 将类实例序列化为JSON
- JSON和对象文字表示法的区别是什么?
- 是否有与XQuery/XPath等价的JSON ?
- 对bash脚本函数中定义的变量使用curl POST
- 从Json转换为类型数组列表<T>
- REST API最佳实践:查询字符串中的参数vs请求体中的参数
- 打印JSON解析对象?
- JSON有查询语言吗?
- 无法加载文件或程序集'Newtonsoft。Json或其依赖项之一。清单定义与程序集引用不匹配
- 错误:不允许匹配“[xX][mM][lL]”的处理指令目标