Convert XML to JSON using XSLT

Published on February 12, 2010

How about that for acronym soup?  In the spirit of doing smaller posts but more often, here is a handy little XSLT. 

Assuming you have the following XML,

 

<Customers>
    <Customer Id="99">
        <Name>Bob</Name>
        <Age>39</Age>
        <Address>
            <Street>10 Idle Lane</Street>
            <City>Yucksville</City>
            <PostalCode>xxxyyy</PostalCode>
        </Address>
    </Customer>
    <Customer Id="101">
        <Name>Bill</Name>
        <Age>39</Age>
        <Address>
            <Street>10 Idle Lane</Street>
            <City>Yucksville</City>
            <PostalCode>xxxyyy</PostalCode>
        </Address>
    </Customer>

</Customers>

 

Using this XSLT

<pre class="csharpcode"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">=&quot;1.0&quot;</span>?<span class="kwrd">&gt;</span>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/>

<span class="kwrd">&lt;</span><span class="html">xsl:template</span> <span class="attr">match</span><span class="kwrd">=&quot;/&quot;</span><span class="kwrd">&gt;</span>{
    <span class="kwrd">&lt;</span><span class="html">xsl:apply-templates</span> <span class="attr">select</span><span class="kwrd">=&quot;*&quot;</span><span class="kwrd">/&gt;</span>}
<span class="kwrd">&lt;/</span><span class="html">xsl:template</span><span class="kwrd">&gt;</span>

<span class="rem">&lt;!-- Object or Element Property--&gt;</span>
<span class="kwrd">&lt;</span><span class="html">xsl:template</span> <span class="attr">match</span><span class="kwrd">=&quot;*&quot;</span><span class="kwrd">&gt;</span>
    &quot;<span class="kwrd">&lt;</span><span class="html">xsl:value-of</span> <span class="attr">select</span><span class="kwrd">=&quot;name()&quot;</span><span class="kwrd">/&gt;</span>&quot; : <span class="kwrd">&lt;</span><span class="html">xsl:call-template</span> <span class="attr">name</span><span class="kwrd">=&quot;Properties&quot;</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">xsl:template</span><span class="kwrd">&gt;</span>

<span class="rem">&lt;!-- Array Element --&gt;</span>
<span class="kwrd">&lt;</span><span class="html">xsl:template</span> <span class="attr">match</span><span class="kwrd">=&quot;*&quot;</span> <span class="attr">mode</span><span class="kwrd">=&quot;ArrayElement&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">xsl:call-template</span> <span class="attr">name</span><span class="kwrd">=&quot;Properties&quot;</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">xsl:template</span><span class="kwrd">&gt;</span>

<span class="rem">&lt;!-- Object Properties --&gt;</span>
<span class="kwrd">&lt;</span><span class="html">xsl:template</span> <span class="attr">name</span><span class="kwrd">=&quot;Properties&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">xsl:variable</span> <span class="attr">name</span><span class="kwrd">=&quot;childName&quot;</span> <span class="attr">select</span><span class="kwrd">=&quot;name(*[1])&quot;</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">xsl:choose</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">xsl:when</span> <span class="attr">test</span><span class="kwrd">=&quot;not(*|@@*)&quot;</span><span class="kwrd">&gt;</span>&quot;<span class="kwrd">&lt;</span><span class="html">xsl:value-of</span> <span class="attr">select</span><span class="kwrd">=&quot;.&quot;</span><span class="kwrd">/&gt;</span>&quot;<span class="kwrd">&lt;/</span><span class="html">xsl:when</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">xsl:when</span> <span class="attr">test</span>=&quot;<span class="attr">count</span>(*[<span class="attr">name</span>()=$<span class="attr">childName</span>]) <span class="kwrd">&gt;</span> 1&quot;<span class="kwrd">&gt;</span>{ &quot;<span class="kwrd">&lt;</span><span class="html">xsl:value-of</span> <span class="attr">select</span><span class="kwrd">=&quot;$childName&quot;</span><span class="kwrd">/&gt;</span>&quot; :[<span class="kwrd">&lt;</span><span class="html">xsl:apply-templates</span> <span class="attr">select</span><span class="kwrd">=&quot;*&quot;</span> <span class="attr">mode</span><span class="kwrd">=&quot;ArrayElement&quot;</span><span class="kwrd">/&gt;</span>] }<span class="kwrd">&lt;/</span><span class="html">xsl:when</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">xsl:otherwise</span><span class="kwrd">&gt;</span>{
            <span class="kwrd">&lt;</span><span class="html">xsl:apply-templates</span> <span class="attr">select</span><span class="kwrd">=&quot;@@*&quot;</span><span class="kwrd">/&gt;</span>
            <span class="kwrd">&lt;</span><span class="html">xsl:apply-templates</span> <span class="attr">select</span><span class="kwrd">=&quot;*&quot;</span><span class="kwrd">/&gt;</span>
}<span class="kwrd">&lt;/</span><span class="html">xsl:otherwise</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">xsl:choose</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">xsl:if</span> <span class="attr">test</span><span class="kwrd">=&quot;following-sibling::*&quot;</span><span class="kwrd">&gt;</span>,<span class="kwrd">&lt;/</span><span class="html">xsl:if</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">xsl:template</span><span class="kwrd">&gt;</span>

<span class="rem">&lt;!-- Attribute Property --&gt;</span>
<span class="kwrd">&lt;</span><span class="html">xsl:template</span> <span class="attr">match</span><span class="kwrd">=&quot;@@*&quot;</span><span class="kwrd">&gt;</span>&quot;<span class="kwrd">&lt;</span><span class="html">xsl:value-of</span> <span class="attr">select</span><span class="kwrd">=&quot;name()&quot;</span><span class="kwrd">/&gt;</span>&quot; : &quot;<span class="kwrd">&lt;</span><span class="html">xsl:value-of</span> <span class="attr">select</span><span class="kwrd">=&quot;.&quot;</span><span class="kwrd">/&gt;</span>&quot;,
<span class="kwrd">&lt;/</span><span class="html">xsl:template</span><span class="kwrd">&gt;</span>

</xsl:stylesheet>

You can generate this JSON

{
    "Customers" : {
        "Customer" : [
            {
                "Id" : "99",
                "Name" : "Bob",
                "Age" : "39",
                "Address" : {
                    "Street" : "10 Idle Lane",
                    "City" : "Yucksville",
                    "PostalCode" : "xxxyyy" 
                } 
            },
            {
                "Id" : "101",
                "Name" : "Bill",
                "Age" : "39",
                "Address" : {
                    "Street" : "10 Idle Lane",
                    "City" : "Yucksville",
                    "PostalCode" : "xxxyyy" 
                } 
            }
        ] 
    }
} 

It would be really interesting to try and use this Javascript XSLT processor to do the transform directly in the browser.  That way any web api that generates XML could be flipped into a JSON representation for direct access in Javascript.