JSON是否有等价的XSLT ?它允许我对JSON进行转换,就像XSLT对XML所做的那样。
当前回答
最近,我围绕着这个写了自己的小库,尽量保持接近
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,
其他回答
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.
我最近发现了一个我喜欢的JSON样式工具:https://github.com/twigkit/tempo。非常容易使用的工具——在我看来,使用它比使用XSLT容易得多——不需要XPATH查询。
Yate (https://github.com/pasaran/yate)是在XSLT之后专门设计的,具有JPath (JS的自然XPath对等物),可以编译为JavaScript,并且在生产中有相当长的使用历史。它实际上没有记录,但阅读样本和测试应该足够了。
有趣的想法。在谷歌上的一些搜索产生了一些有趣的页面,包括:
如何实现这样一个“jsonT”工具的概述,以及一些下载 关于该实现的一些讨论 一个公司可能已经实施了一些合适的东西
希望这能有所帮助。
有关利用纯JavaScript的方法以及XSLT匹配表达式和递归模板背后熟悉的声明式模式的工作演示/概念证明,请参见https://gist.github.com/brettz9/0e661b3093764f496e36
(JSON也可以采用类似的方法。)
注意,为了方便在Firefox中表达模板,演示还依赖于JavaScript 1.8表达式闭包(至少在实现方法的ES6简写形式之前是如此)。
免责声明:这是我自己的代码。
推荐文章
- 如何检查JSON键是否存在?
- 具有多个条件的XPath
- 将对象序列化为JSON
- node.js TypeError:路径必须是绝对路径或指定根路径到res.sendFile[解析JSON失败]
- Python json。loads显示ValueError:额外数据
- JSON省略了Infinity和NaN;JSON在ECMAScript中的状态?
- console.log(result)输出[object对象]。我如何得到result。name?
- 在XSLT中生成新行
- java8 LocalDate Jackson格式
- 在Go中使用JSON Marshal的小写JSON键名
- jQuery发布JSON
- 如何将FormData (HTML5对象)转换为JSON
- 我如何从资产文件夹解析一个本地JSON文件到一个ListView?
- 使用Python将XML转换为JSON ?
- 在ASP中设置Access-Control-Allow-OriginNet MVC -最简单的方法