XSON相当于JSON
是否有与JSON相当的XSLT ? 有些东西可以让我像XSLT一样对JSON进行转换对XML。
有趣的想法。 Google上的一些search产生了几页兴趣,包括:
- 这个“jsonT”工具如何实现的概要以及一些下载
- 对这个实施的一些讨论
- 一个可能已经实施了一些合适的公司
希望这可以帮助。
试试JOLT 。 这是用Java编写的JSON转换库的JSON。
它是专门创build的,因为我们不想玩“JSON→XML→XSLT→XML→JSON”游戏,并且使用模板进行任何足够复杂的转换是不可维护的。
我最近find了一个我喜欢的样式JSON的工具: http : //twigkit.github.com/tempo/ 。 使用非常简单的工具 – 在我看来,使用XSLT要容易得多 – 不需要XPATH查询。
jq – 轻量级和灵活的命令行JSON处理器
它不像XSLT那样基于模板,但更简洁。 例如将name
和address
字段提取到数组中: [.name, .address]
name
[.name, .address]
本教程将演示如何转换Twitter的JSON API(本手册中有很多示例)。
看看jsonpath-object-transform
XSLT支持JSON,见http://www.w3.org/TR/xslt-30/#json
XML使用尖括号作为分隔标记,JSON使用大括号,方括号,… I. e。 XML的令牌识别比较较less意味着它为声明式转换进行了优化,而为了速度的原因,更多的比较(如switch语句)则假设脚本语言中的命令式编码对预测的分支预测是有用的。 作为直接结果,对于不同的半结构化数据混合,您可能希望将XSLT和JavaScript引擎的性能作为响应式页面的一部分。 对于微不足道的数据负载,转换可能与没有XML序列化的JSON一样好。 W3的决定应该基于更好的分析。
说缺乏工具意味着缺乏需要就是乞讨这个问题。 为什么要在Linux中支持X或Y(为什么要为这样一个less数系统开发质量驱动和/或游戏?为什么要关注一个大型游戏和硬件公司没有开发的操作系统?)。 可能需要使用XSLT和JSON的人最终会使用一些不重要的解决方法:将JSON转换为XML。 但这不是最佳解决scheme,是吗?
当你有一个原生的JSON格式,你想在浏览器中编辑它“wysywyg”,XSLT将是一个比这个问题更充分的解决scheme。 这样做与传统的JavaScript编程可以成为一个痛苦的屁股。
事实上,我已经实现了XSLT的“石器时代”方法,使用子stringparsing来解释JavaScript的一些基本命令,如调用模板,处理子元素等。当然,使用JSON对象实现转换引擎比实现一个完整的XMLparsing器来parsingXSLT。 问题是,要使用XML模板来转换JSON对象,您需要parsing模板的XML。
要使用XML(或HTML,或文本或其他)转换JSON对象,您需要仔细考虑语法以及需要使用哪些特殊字符来标识转换命令。 否则,你最终将不得不为你自己的自定义模板语言devise一个parsing器。 走过那条路,我可以告诉你,这不是很好。
更新(2010年11月12日):经过几个星期的parsing器工作,我已经能够优化它。 预先parsing模板,并将命令存储为JSON对象。 转换规则也是JSON对象,而模板代码是混合了HTML和类似于shell代码的自制语法。 我已经能够将复杂的JSON文档转换为HTML来制作文档编辑器。 对于编辑器(这是一个私人项目,所以我不能分享它)和JSON转换代码(包括迭代命令,简单比较,模板调用,variables保存和评估)的990行左右的代码约为1K行。 我计划在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的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的比较:
相当于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问题 (当然还有其他问题)所提出的祖先轴进行查询。
例如,如何获得知道其品牌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" } ] }
?
可能的解决scheme是:
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,
作为老问题的又一个新的答案,我build议看看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>
现在有! 我最近创build了一个库, json转换 ,完全是为了这个目的:
https://github.com/ColinEberhardt/json-transforms
它使用JSPath (一种基于XPath的DSL)和recursion模式匹配方法(由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
属性的物体,然后recursion匹配。 第二条规则匹配具有maker
属性的任何对象,输出model
和year
属性。 最后是recursion匹配的身份转换。
我已经厌倦了那里的大量JavaScript模板引擎,以及所有内联HTML模板,不同的标记样式等,并决定构build一个小型库 ,以便为JSON数据结构启用XSLT格式。 不是任何方式的火箭科学 – 它只是parsing为XML的JSON,然后用XSLT文档格式化。 它速度也很快,不如Chrome浏览器中的JavaScript模板引擎快,但是在大多数其他浏览器中,它至less与大型数据结构的JS引擎替代速度一样快。
JSONiq就是这样一个标准, Zorba是一个开源的C ++实现。 JSONiq也可以被视为XQuery,并将JSON添加为本机数据types。
我正在使用骆驼路由umarshal(xmljson) – >到(xlst) – > marshal(xmljson)。 足够高效(尽pipe不是100%完美),但如果您已经在使用骆驼,那么很简单。
不太确定是否需要这个,而对我来说缺乏工具暗示缺乏需要。 JSON最好作为对象进行处理(它在JS中完成的方式),而且通常使用对象本身的语言来进行转换(从JSON创build的Java对象的Java,对于Perl,Python,Perl,c#,PHP等上)。 只是正常的任务(或设置,获取),循环等。
我的意思是说,XSLT只是另一种语言,需要的一个原因是XML不是一个对象符号,因此编程语言的对象并不是精确匹配(分层XML模型和对象/结构之间的阻抗)。
使用XSLT转换JSON是非常可能的:您需要JSON2SAX解串器和SAX2JSON序列化器。
Java示例代码: http : //www.gerixsoft.com/blog/json/xslt4json
Yate( https://github.com/pasaran/yate )是在XSLT之后专门devise的,具有JPath特性(与JS相当的自然XPath),编译成JavaScript,并且具有相当丰富的生产历史。 它实际上没有logging,但通过样品和testing应该是足够的。
为什么不使用Data Coverter将JSON转换为XML,使用XSLT对其进行转换,然后使用相同的方法将其更改回JSON。
对于使用纯JavaScript以及XSLT匹配expression式和recursion模板背后的熟悉和声明模式的工作方式的涂鸦/概念validation,请参阅https://gist.github.com/brettz9/0e661b3093764f496e36
(JSON可能采取了类似的方法。)
请注意,演示还依赖于JavaScript 1.8expression式闭包,以方便在Firefox中表示模板(至less直到可以实现方法的ES6简写forms)。
免责声明:这是我自己的代码。
我很久以前为我的jacksonjson处理框架写了一个dom适配器。 它使用nu.xom库。 生成的dom树与java xpath和xslt工具一起使用。 我做了一些非常简单的实现select。 例如,根节点总是被称为“根”(root),数组进入具有li子元素的ol节点(就像在html中一样),而其他一切只是具有原始值的子节点或另一个对象节点。
JsonXmlConverter.java
用法: JsonObject sampleJson = sampleJson(); org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson, "root");
JsonObject sampleJson = sampleJson(); org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson, "root");
尚未给出的一种方法是使用parsing器生成器在XSLT中创buildparsing器,parsingJSON并生成XML输出。
在XML会议上被提及的一个选项是ReXparsing器生成器( http://www.bottlecaps.de/rex/ ) – 尽pipe在网站上完全没有文档,但是在search时可以使用食谱。