Transforming JSON to XML using Mustache
I had the need recently to take a deeply-nested JSON structure and transform it to a relatively flat XML file. Ideally I wanted the equivalent of XPath for JSON, where I could have flattened a nested structure like this:
[
{ name: form1, fields: [ ... ] },
{ name: form1, fields: [ ... ] }
]
using XPath to select the fields:
//fields
I had been using the following custom bit of code to apply a flat template to a Javascript array, which I could have applied to the nodeset from the XPath listed above.
function applyTemplate( data, template ) {
for( var i=0; i < data.length; i++ ) {
var output = template;
var item = data[i];
for( field in item ) {
var regex = new RegExp( "\\${" + field + "}", "g" );
output = output.replace( regex, item[field] );
}
WScript.Echo( output );
}
}
This very simply applied the entire template to each item in the array, replacing ${} tags with corresponding fields on the JS objects. I had to do some manual work to cobble together the entire output that I wanted using this quick-and-dirty script. I was trying to avoid using a template language but now that I wanted to do nested repetitions I didn’t want to spend the time to write any more code.
I looked around for something that would let me do something similar to what I did in Jath to go from XML to JSON. I found an interesting hack for making jQuery work against JS objects, but I really wanted something more declarative than functional in this case.
I found JsonPath, which only solved half of my problem — that is, the selection of source data. I would have had to use my hack script to do the rest of the job. The closest thing that I found in Javascript to solve the problem was JsonT. JsonT looks interesting, but I wasn’t too crazy about having to write so many individual rules to do what I wanted. It felt like doing XSLT where you are applying a ton of small rules and it is hard to see at a glance what your output looks like.
I was afraid I’d end up using something like StringTemplate or one of the Ruby template engines that Rails uses. But, I found a Javascript implementation of Mustache called mustache.js.
I’m using JScript under Windows Script Host here, and mustache.js worked just fine in this environment. I was thinking that I’d have to provide my own lambda functions in order to get the data that I needed from the source JS object since it didn’t look like Mustache supported nested objects. For example, you can’t say:
{{#form.fields}}
....
{{/form.fields}}
You can, however reference a function, so my source data would have had to be a wrapper around my actual data. For example:
var data = {
name: "form1",
fields: function() {
/* iterate through source data */
return fields;
}
}
Then we could do:
{{#fields}}
....
{{/fields}}
without having to use dot notation. The real reason for this post, however, is to show how nested enumerable sections work. I realized that we could emulate the equivalent of XPath’s ‘/form/fields’ using the following:
{{#form}}{{#fields}}
.....
{{/fields}}{{/form}}
My template now looks something like:
<Entities>
{{#form}}{{#fields}}
<Entity><Name>{{name}}</Name><ID>{{id}}</ID></Entity>
{{/fields}}{{/form}}
</Entities>
Hopefully this helps someone out. There are a lot of JSON to XML and XML to JSON libraries out there, but most of them are pretty specific to one thing. For template-based XML to JSON using XPath queries check out my Jath project. For rule-based JSON to XML serialization JsonT is pretty interesting, and I have a project that is aimed at providing rule-based namespace support for XML serialization called js-xml-serializer (I ran out of fun names).