Convert XML to JSON using XSLT

With increasing use of separate services on the same data, the need for portable data formats aroused. XML was one of the first widely used, but lately JSON is blooming.

I don’t have a particular bias here, both serve well in appropriate environment, although JSON carrying the same data could result in about 20% size reduction.

So can they be interchangeable? Just recently, I needed to convert XML data into a JSON format for easier consumption on the client.

The fastest and (sometimes) easiest way to process XML to another format is XSLT.

Downloads

Links

The full XSLT code is at the bottom of this post and on GitHub.

Performing the transformation

Using XSLT to transform XML to another format is pretty easy, as it’s meant to be. :)

Depending on the environment you are running when you need this, there are different ways you can perform the transformation.

What’s important to note is that the same XSLT is used in all of these methods.

Specifying the stylesheet in XML

The easiest would be to just add a stylesheet to you XML document.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="xml2json.xsl"?>
<!-- ... XML ... -->

Just open such a XML file in a browser, and the JSON will be there. Here’s an example page, you will see JSON when you open it, but if you view the source code, you will see XML only. The browser is applying the transformation.

Use an executable to transform XML to JSON

Microsoft provides msxsl.exe, a free command line utility to perform transformations, but it works only with MSXML 4.0 libraries (link). So it’s not really usable on Windows 7, for example.

I created a similar, but .NET based command line utility and, here is xsltr.exe that you can download.

C# code excerpt

It boils down to this…

doc = new XPathDocument(xmlfile);
XslCompiledTransform transform = new XslCompiledTransform(true);
transform.Load(xslfile);
XmlTextWriter writer = new XmlTextWriter(outfile, null);
transform.Transform(doc, null, writer);

Compiling the XSLT

But if you need the performance, here is a command line utility  together with the compiled XSLT.

I used the xsltc.exe to create a compiled xslt from the source code. It will compile the XSLT code to IL assembly and it will perform the transformation much faster.

Transform XML to JSON in a browser using JavaScript

To work with XML, DOMParser can be used in all the modern browsers – Firefox, Opera, Chrome, Safari… Of course, Internet Explorer has it’s own Microsoft.XMLDOM class.

Here’s a demo page that performs the transformation. There are a couple of XML files that you can transform, but you can also enter arbitrary XML and transform it.

If you prefer to work with libraries, I tried jsxml and it worked flawlessly.

The pure JavaScript code boils down to these pieces.

Load a string into an XML DOM JavaScript (code excerpt)

// code for regular browsers
if (window.DOMParser) {
    var parser = new DOMParser();
    demo.xml = parser.parseFromString(xmlString, &amp;quot;application/xml&amp;quot;);
}
// code for IE
if (window.ActiveXObject) {
    demo.xml = new ActiveXObject(&amp;quot;Microsoft.XMLDOM&amp;quot;);
    demo.xml.async = false;
    demo.xml.loadXML(xmlString);
}

Apply the XSLT JavaScript code excerpt

// code for regular browsers
if (document.implementation && document.implementation.createDocument)
{
    var xsltProcessor = new XSLTProcessor();
    xsltProcessor.importStylesheet(demo.xslt);
    result = xsltProcessor.transformToFragment(demo.xml, document);
}
else if (window.ActiveXObject) {
    // code for IE
    result = demo.xml.transformNode(demo.xslt);
}

You can see this in action on the demo page.

XSLT Code

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="utf-8"/>
    <xsl:template match="/*[node()]">
        <xsl:text>{</xsl:text>
        <xsl:apply-templates select="." mode="detect" />
        <xsl:text>}</xsl:text>
    </xsl:template>
    <xsl:template match="*" mode="detect">
        <xsl:choose>
            <xsl:when test="name(preceding-sibling::*[1]) = name(current()) and name(following-sibling::*[1]) != name(current())">
                    <xsl:apply-templates select="." mode="obj-content" />
                <xsl:text>]</xsl:text>
                <xsl:if test="count(following-sibling::*[name() != name(current())]) > 0">, </xsl:if>
            </xsl:when>
            <xsl:when test="name(preceding-sibling::*[1]) = name(current())">
                    <xsl:apply-templates select="." mode="obj-content" />
                    <xsl:if test="name(following-sibling::*) = name(current())">, </xsl:if>
            </xsl:when>
            <xsl:when test="following-sibling::*[1][name() = name(current())]">
                <xsl:text>"</xsl:text><xsl:value-of select="name()"/><xsl:text>" : [</xsl:text>
                    <xsl:apply-templates select="." mode="obj-content" /><xsl:text>, </xsl:text>
            </xsl:when>
            <xsl:when test="count(./child::*) > 0 or count(@*) > 0">
                <xsl:text>"</xsl:text><xsl:value-of select="name()"/>" : <xsl:apply-templates select="." mode="obj-content" />
                <xsl:if test="count(following-sibling::*) > 0">, </xsl:if>
            </xsl:when>
            <xsl:when test="count(./child::*) = 0">
                <xsl:text>"</xsl:text><xsl:value-of select="name()"/>" : "<xsl:apply-templates select="."/><xsl:text>"</xsl:text>
                <xsl:if test="count(following-sibling::*) > 0">, </xsl:if>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="*" mode="obj-content">
        <xsl:text>{</xsl:text>
            <xsl:apply-templates select="@*" mode="attr" />
            <xsl:if test="count(@*) > 0 and (count(child::*) > 0 or text())">, </xsl:if>
            <xsl:apply-templates select="./*" mode="detect" />
            <xsl:if test="count(child::*) = 0 and text() and not(@*)">
                <xsl:text>"</xsl:text><xsl:value-of select="name()"/>" : "<xsl:value-of select="text()"/><xsl:text>"</xsl:text>
            </xsl:if>
            <xsl:if test="count(child::*) = 0 and text() and @*">
                <xsl:text>"text" : "</xsl:text><xsl:value-of select="text()"/><xsl:text>"</xsl:text>
            </xsl:if>
        <xsl:text>}</xsl:text>
        <xsl:if test="position() < last()">, </xsl:if>
    </xsl:template>
    <xsl:template match="@*" mode="attr">
        <xsl:text>"</xsl:text><xsl:value-of select="name()"/>" : "<xsl:value-of select="."/><xsl:text>"</xsl:text>
        <xsl:if test="position() < last()">,</xsl:if>
    </xsl:template>
    <xsl:template match="node/@TEXT | text()" name="removeBreaks">
        <xsl:param name="pText" select="normalize-space(.)"/>
        <xsl:choose>
            <xsl:when test="not(contains($pText, '
'))"><xsl:copy-of select="$pText"/></xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="concat(substring-before($pText, '
'), ' ')"/>
                <xsl:call-template name="removeBreaks">
                    <xsl:with-param name="pText" select="substring-after($pText, '
')"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

The XSLT code turned out to be more complicated then I expected- I imagined that the transformation would be more natural, not so case based, but it just isn’t possible (or I don’t see the way).

License

MIT License

Copyright (c) 2012 Bojan Bjelic

Full license text (on Choose a license site).

Resources

Links to the resources I used in the process.

Comments

69 responses to “Convert XML to JSON using XSLT”

  1. raju Avatar

    can we apply xsl to a text file to get json response

    1. Bojan Bjelić Avatar

      Sorry Raju,
      But xslt is meant to work only with xml – you’ll have to use some other kind of conversion.

  2. Edward Avatar

    Thank you for this template, this is the best XML to JSON XSLT implementation I’ve come across!

    1. Bojan Bjelić Avatar

      Thanks Edward, glad you like it!

  3. Jean-Philippe Martin Avatar
    Jean-Philippe Martin

    Great script !
    I made a modification : On the line 48 :

    +

    Because my xml contained carriage returns in the CDATA : ex:

    1. Jean-Philippe Martin Avatar
      Jean-Philippe Martin

      Oups my code got stripped !
      I added a normalize-space around text() on line 48.

      My CDATA was :
      ![CDATA[ObjDesCadres_Type3]]

      1. Bojan Bjelić Avatar

        Hey Jean-Phillpe, glad to see you found good use of it. The removeBreaks template should be taking care of the line breaks…
        If you send me the XML you’re processing to my email, I’ll take a look.
        Best, Bojan

  4. Michael B. Avatar

    Thank you for this Bojan, but it looks like your dropbox file or folder has disappeared. I have a lot of xml files that I’d like to convert to json (on the command line), and the .NET utility that you refer to cannot be found. ie, from this, above:

    I created a similar, but .NET based command line utility and, here is xsltr.exe that you can download.

    Or am I missing something? Thanks!

    ( As far as I can tell yours would be the only command line utility “out there”… )

    1. Bojan Bjelić Avatar

      Hi Michael, the xsltr.exe is back in the dropbox – sorry about that.

      If you can use the xslt as-is, and need to get done quickly, I suggest you use the xml2json.zip, the transformation is compiled there.

      1. Michael B. Avatar

        Thanks Bojan. Incidentally, in the meantime, I got the “Microsoft” method to work on Windows 7, using Service Pack 3 of the MSXML 4.0 core services (at http://www.microsoft.com/en-us/download/details.aspx?id=15697).

        Good news is that both conversions of an 11k file were identical, so I’m assuming they are both correct, consistent and complete! :)

  5. Mihir Avatar
    Mihir

    I am totally new to this, and thus dont know how to fix when my xml contains some text: including our “Ready4Retail” standard: a 90-plus-point inspection. Any ideas?
    ITs not properly parsing and giving an error:
    Error: Parse error on line 1:
    …ards including our “Ready4Retail” standa
    ———————–^
    Expecting ‘EOF’, ‘}’, ‘:’, ‘,’, ‘]’

    Thanks

    1. Bojan Bjelić Avatar

      The problem is (probably) that the values in JSON are enclosed in quotes… The solution would be to escape the quotes before running the conversion.

      1. Mihir Avatar
        Mihir

        Thank you much…..

  6. Vivek Avatar
    Vivek

    Bojan,

    This script is awesome! Thanks for publishing it.

    Is there a way to strip the root node from the JSON output? Appreciate your input on this.

    1. Bojan Bjelić Avatar

      Hi Vivek,
      You’re very welcome.
      Didn’t try this, but to skip the root, the solution should be to select whatever node comes first under the root. To achieve this, the value for match=”/*[node()]” attribute in the line 5 should be replaced by another xpath. Let me know if this works out.
      Cheers, Bojan

  7. cuq Avatar
    cuq

    Thanks! a LOT!

  8. henry Avatar
    henry

    this is great

  9. […] pass it through one of the many XML to JSON XSLT templates I came across online. This one is from Convert XML to JSON using XSLT and the output looks […]

  10. Ernest Avatar
    Ernest

    Hello,
    nice template, I’m trying modify it to work this way:

    xml:

    <Fruit>
    <Apple>xx</Apple>
    <Orange>aa</Orange>
    <Orange>bb</Orange>
    </Fruit>

    to be converted in:

    {
    Fruit: {
    "Apple":"xx",
    "Orange":["aa","bb"]
    }
    }

    I’m having quite a bit difficulty with this (very basic xslt knowledge), help or tip maybe?

    1. Bojan Bjelić Avatar

      Hi Ernest,
      I tried to compose the XSLT in a very generic fashion, so it fits different markup and use cases.

      The change you want would require checking if the nodes of same name have no attributes and then render just the text content.

      This case is starting on the line 21:

      <xsl:when test="following-sibling::*[1][name() = name(current())]">

      So you could start working from there. Hope this helps.

  11. Ernest Avatar
    Ernest

    Managed to get it work in the meantime. Actual changes were made in obj-content template, here is changed version:

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="utf-8"/>

    <xsl:template match="/*[node()]">
    <xsl:text>{</xsl:text>
    <xsl:apply-templates select="." mode="detect" />
    <xsl:text>}</xsl:text>
    </xsl:template>

    <xsl:template match="*" mode="detect">
    <xsl:choose>
    <xsl:when test="name(preceding-sibling::*[1]) = name(current()) and name(following-sibling::*[1]) != name(current())">
    <xsl:apply-templates select="." mode="obj-content" />
    <xsl:text>]</xsl:text>
    <xsl:if test="count(following-sibling::*[name() != name(current())]) &gt; 0">, </xsl:if>
    </xsl:when>
    <xsl:when test="name(preceding-sibling::*[1]) = name(current())">
    <xsl:apply-templates select="." mode="obj-content" />
    <xsl:if test="name(following-sibling::*) = name(current())">, </xsl:if>
    </xsl:when>
    <xsl:when test="following-sibling::*[1][name() = name(current())]">
    <xsl:text>"</xsl:text><xsl:value-of select="name()"/><xsl:text>" : [</xsl:text>
    <xsl:apply-templates select="." mode="obj-content" /><xsl:text>, </xsl:text>
    </xsl:when>
    <xsl:when test="count(./child::*) > 0 or count(@*) > 0">
    <xsl:text>"</xsl:text><xsl:value-of select="name()"/>" : <xsl:apply-templates select="." mode="obj-content" />
    <xsl:if test="count(following-sibling::*) &gt; 0">, </xsl:if>
    </xsl:when>
    <xsl:when test="count(./child::*) = 0">
    <xsl:text>"</xsl:text><xsl:value-of select="name()"/>" : "<xsl:apply-templates select="."/><xsl:text>"</xsl:text>
    <xsl:if test="count(following-sibling::*) &gt; 0">, </xsl:if>
    </xsl:when>
    </xsl:choose>
    </xsl:template>

    <xsl:template match="*" mode="obj-content">
    <xsl:apply-templates select="@*" mode="attr" />
    <xsl:if test="count(@*) &gt; 0 and (count(child::*) &gt; 0 or text())">, </xsl:if>
    <xsl:apply-templates select="./*" mode="detect" />
    <xsl:if test="count(child::*) = 0 and text() and not(@*) and (name(preceding-sibling::*[1]) = name(current()) or name(following-sibling::*[1]) = name(current()))">
    <xsl:text>"</xsl:text><xsl:value-of select="text()"/><xsl:text>"</xsl:text>
    </xsl:if>
    <xsl:if test="count(child::*) = 0 and text() and not(@*) and name(preceding-sibling::*[1]) != name(current()) and name(following-sibling::*[1]) != name(current())">
    <xsl:text>{"</xsl:text><xsl:value-of select="name()"/>" : "<xsl:value-of select="text()"/><xsl:text>"}</xsl:text>
    </xsl:if>
    <xsl:if test="count(child::*) = 0 and text() and @*">
    <xsl:text>{"text" : "</xsl:text><xsl:value-of select="text()"/><xsl:text>"}</xsl:text>
    </xsl:if>
    <xsl:if test="position() &lt; last()">, </xsl:if>
    </xsl:template>

    <xsl:template match="@*" mode="attr">
    <xsl:text>"</xsl:text><xsl:value-of select="name()"/>" : "<xsl:value-of select="."/><xsl:text>"</xsl:text>
    <xsl:if test="position() &lt; last()">,</xsl:if>
    </xsl:template>

    <xsl:template match="node/@TEXT | text()" name="removeBreaks">
    <xsl:param name="pText" select="normalize-space(.)"/>
    <xsl:choose>
    <xsl:when test="not(contains($pText, ' '))"><xsl:copy-of select="$pText"/></xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="concat(substring-before($pText, ' '), ' ')"/>
    <xsl:call-template name="removeBreaks">
    <xsl:with-param name="pText" select="substring-after($pText, ' ')"/>
    </xsl:call-template>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:template>

    </xsl:stylesheet>

  12. Smita Avatar
    Smita

    Can anybody help me in acheiving this,
    I want a similar logic of converting xml to text file but not json so
    when input:

    RNILF04
    true
    479

    output
    should be:

    scores:
    score:
    sourcedFrom: SCO
    scoreLabel : RNILF04
    positive : true
    value : 479

    1. Bojan Bjelić Avatar

      Hi Smita,
      The code got stripped from the comment, please either contact me directly or try editing the comment…

  13. Daniel Avatar
    Daniel

    This ends up with a stack overflow for xml containing a single element, any ideas how this might be fixed?

    i.e.

    There is an error

    1. Bojan Bjelić Avatar

      Hi Daniel, I can confirm your finding.

    2. Bojan Bjelić Avatar

      Hi Daniel,
      FWIW – this is fixed, you can have a look on GitHub repo: https://github.com/bojanbjelic/xml2json

  14. Jon Avatar
    Jon

    This converter doesn’t seem to capture mixed text+tag content. E.g. if I feed it

    Text A Text Asub Text A2 Text A2sub

    the result is

    {“root” : {“node” : {“subnode” : [{“subnode” : “Text Asub”}
    , {“subnode” : ” Text A2sub “}
    ]}
    }
    }

    and the “Text A” / “Text A2” content is lost. Any thoughts on this? At first this looked like a good solution, but this limitation means loss of information from my actual XML content.

    Also, I’m a bit curious on a couple of choices you made which seem to make inverting the transformation more difficult: first, XML attributes and nested tags aren’t distinguished in the output (aside from the attributes being emitted first), and second, when multiple tags of the same name occur in order, they’re converted to a single JSON array. I understand these are essentially arbitrary choices but am curious what the rationale was. In particular, emitting the attributes inside an “xml-attrib”: array or something like that seems like a reasonable option.

    I probably can remind myself of enough XSL to make the last two changes, but I’m not sure I’ve ever been familiar enough with XSL to address the mixed text/tag content issue :-(

    1. Jon Avatar
      Jon

      Erggh. The XML tags were stripped from the comment on posting. See http://pastebin.com/rw0gdJLy for the source.

    2. Bojan Bjelić Avatar

      Hi Jon, you are right I never considered mixed text and element content.
      The choices you mentioned were completely arbitrary, just what seemed like a right solution at the time. Would be great if you would create a branch with different output on github https://github.com/bojanbjelic/xml2json/ :).

  15. Mahesh Avatar
    Mahesh

    name spaces are not getting populated in JSON by using above XSLT..Do u have any other templates which will work for namespaces..thanks Mahesh

    1. Bojan Bjelić Avatar

      Hi Mahesh, sorry but there’s no support for namespaces at this point

  16. Costantino Avatar
    Costantino

    Hi,
    I get the following transformation error

    LPX-00118: Warning: undefined entity “egrave”
    Error at line 1

    if a node contain the following text:

    “This is a html formatted text with è character”

    Maybe it is raised by the removeBreaks template.

    BR
    Costantino

    1. Bojan Bjelić Avatar

      Hi Constantino, thanks for notifying me.
      I would say that this is not valid XML, should look like This is a html formatted text with &egrave; character, so escaping the ampersand entity first since XML doesn’t support “egrave”. https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined_entities_in_XML

      1. Costantino Avatar
        Costantino

        Hi Bojan,
        this is what I wrote but that character has been re-rendered by your web site.
        If you put what you wrote exactly in an xml you can get the error I mentioned.

        BR
        Costantino

        1. Bojan Bjelić Avatar

          I know – seems the site rendered it in my comment as well :)
          &egrave; is an unknown XML entity, the XML is not valid with that.
          You would need to escape it, like so &amp;egrave;

  17. Gas Avatar
    Gas

    Hello Bojan,
    I do need often to convert xml2json at work but I didn’t find a good answer to a question: how to preserve arrays?
    In the second example below, I would like to preserve the structure of the produced json having an array node: suggestions?

    Example – 2 ‘b’ nodes produce a json with ‘”b”: [ … ]”

    1st a node
    1st b node
    2nd b node

    {
    “root”: {
    “a”: “1st a node”,
    “b”: [{ “b”: “1st b node” }, { “b”: “2nd b node” }]
    }
    }

    Example – 1 ‘b’ nodes produce a json with ‘”b”: { … }”

    1st a node
    1st b node

    {
    “root”: {
    “a”: “1st a node”,
    “b”: “1st b node”
    }
    }

    Regards,
    Gas

    1. Bojan Bjelić Avatar

      Sorry Gas,
      The xslt in the current form treats each XML separately. The arrays appear only when there is more than one element with the same name as immediate siblings.
      If you want the output to treat “b” always as array I would suggest modifying the XSLT.

  18. John Carlson Avatar
    John Carlson

    I’m dealing with an existing XSLT stylesheet that outputs (line breaks I presume) in the XML to JSON transformation. Whitespace is allowed in JSON, and the stylesheet and file input work okay in xmlsh. I am using Chrome and trying to get this to work:

    if (document.implementation && document.implementation.createDocument) {
    // code for regular browsers
    var xsltProcessor = new XSLTProcessor();
    xsltProcessor.importStylesheet(xslt);
    result = xsltProcessor.transformToFragment(xml, document);
    } else if (window.ActiveXObject) {
    // code for IE
    result = xml.transformNode(xslt);
    }

    but the result only contains the first line of the stylesheet output. I presume I’ll have to add a parameter to the stylesheet so that line breaks are not added to the JSON, possibly enabling something similar to your removeBreaks template–does removeBreaks work on output JSON? I am not that familiar with XSLT. Alternatively, could you try to put line breaks in your output JSON (say right after the beginning of a JSON object–I can try it too) and see what happens? Is there different output line break we should be using to process this stylesheet in a browser? #xA?

    1. John Carlson Avatar
      John Carlson

      The stylesheet is outputting for line breaks I believe.

    2. John Carlson Avatar
      John Carlson

      I was able to use your stylesheet with my code to generate JSON. So the problem appears to be with our stylesheet. Do you know a way for browsers to notify you of errors? I can only assume that the errors are caused stylesheet, and the stylesheet needs to be fixed so the browser can recognize it. Is there a special incantation not listed on this page for XSLT 2.0?

      1. John Carlson Avatar
        John Carlson

        I used SaxonCE available here: http://saxonica.com/ce/index.xml The code is very similar. I am not sure if this works with IE, you may have to track that down:

        function onSaxonLoad() {
        $.get(“X3dToJson.xslt”, function(xslt) {
        var xmlString = document.getElementById(‘xml’).value;
        console.log(“VAL”, xmlString);
        var demo = { xslt: xslt};

        // code for regular browsers
        if (window.DOMParser) {
        var parser = new DOMParser();
        demo.xml = parser.parseFromString(xmlString, “application/xml”);
        }
        // code for IE
        if (window.ActiveXObject) {
        demo.xml = new ActiveXObject(“Microsoft.XMLDOM”);
        demo.xml.async = false;
        demo.xml.loadXML(xmlString);
        }
        console.log(“PARSED XML”, demo.xml);

        // code for regular browsers
        if (document.implementation && document.implementation.createDocument)
        {
        var xsltProcessor = Saxon.newXSLT20Processor();
        xsltProcessor.importStylesheet(demo.xslt);
        result = xsltProcessor.transformToFragment(demo.xml, document);
        }
        else if (window.ActiveXObject) {
        // code for IE
        result = demo.xml.transformNode(demo.xslt);
        }

        console.log(‘JSON’, result);
        document.getElementById(‘json’).value = getXmlString(result);
        }, “xml”);
        };

        1. Bojan Bjelić Avatar

          Hi John,
          My stylesheet won’t output the linebreaks as you can see on the example page http://www.bjelic.net/xml2json/transform.html

          Unfortunately I’m not familiar with that library so I can’t offer much help there.

  19. Baidhyanath Avatar
    Baidhyanath

    Hi,
    I need to pass a xml to your published xslt,so that the passed xml is converted into JSON.

    Let me know how can I pass it to your xslt and what are the changes required in your xslt so that it will change the passed xml to JSON.

    Appreciating your efforts

    1. Bojan Bjelić Avatar

      Hi – I’m afraid you’ll need to run the conversion yourself.
      If it’s a one-off you could do it using the demo page though…
      Hope that helps.

  20. Dwayne Avatar
    Dwayne

    http://www.bjelic.net/2012/08/01/coding/convert-xml-to-json-using-xslt/
    https://github.com/bojanbjelic/xml2json/blob/master/xml2json.xsl

    Hi Bojan,
    This XSLT is awesome. I’m not great with XSLT but I was wondering, what if my XML had some actual HTML in it that I didn’t want converted to JSON? How would I just do a xsl:copy-of on certain element(s) while still removing new lines, like all “HTMLContent” elements? My sample XML is in this Google doc:
    https://docs.google.com/document/d/1bYTakrCV58SRgQlt6lIToPkcjw0IDwp6Un5PcFN-_FM/edit?usp=sharing

    Also, for some reason this Sample XML isn’t getting all the new lines removed when transformed to JSON.

    PS: Do you have a JSON to XML transform too?

  21. Bojan Bjelić Avatar

    Hi Dwayne,
    You could extend the xslt to recognize particular element and then apply a different template, for example:

        <xsl:template match="*" mode="detect">
            <xsl:choose>
                <xsl:when test="name()='HTMLContent'">
                    <xsl:value-of select="current()"/>
                </xsl:when>
                ...
    

    Unfortunately, I don’t have a solution that would work the other way around (JSON to XML).

  22. Anuj Avatar
    Anuj

    Hi Bojan,

    can you help me in converting below xml into specific type of json?

    1. Bojan Bjelić Avatar

      Hi Anuj,
      Unfortunately WordPress stripped away the XML code.
      Anyway the comment section is not quite the place for this – send me an email, post to GitHub, or another way please.
      Bojan

  23. jan mook Avatar
    jan mook

    Could you tell me what the license agreement of your xslt code. is is MIT license ?

    1. Bojan Bjelić Avatar

      Hi Jan,
      Yes, you can treat this as having the MIT license – I just added that information to the page and GitHub repo.

  24. Andros Avatar
    Andros

    Really Nice XSLT to JSON transformer.
    Will use this to send XML from server to Javascript client, let client transform to Json and then make javascript objects.

    1. Bojan Bjelić Avatar

      Hi Andros, sure – that’s doable, but you should consider also doing this server-side and sending JSON to the client, since JSON is typically smaller in size than XML.

  25. Mark Avatar
    Mark

    Hey Bojan, really useful code – thank you very much.
    I wonder if it’s possible to extend it such that double quotes can be escaped in the JSON output:

    This is “my” test

    {
    “tag”: “This is \”my\” test”
    }

    I found the below code on Stack Overflow, but I’m new to XSLTs and don’t understand how to implement it.

    0″>

    \”

    1. Bojan Bjelić Avatar

      Hi Mark, unfortunately the XML code is gone – could you try editing your comment?

  26. Nagarjun Avatar
    Nagarjun

    Hi Bojan,

    i Have the same requirement. but instead of passing files i have to send as a string paramaneter. below is the code that i have implemented. its generation JSON in a string format nut not in a json object format, i want in a object format.

    public String transform(String input,String template){
    try {
    StringWriter writer = new StringWriter();
    TransformerFactory factory = TransformerFactory.newInstance();
    InputStream templateStream = new ByteArrayInputStream(template.getBytes(StandardCharsets.UTF_8));
    InputStream inputStream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8));
    Source xslt = new StreamSource(templateStream);
    Transformer transformer = factory.newTransformer(xslt);

    Source text = new StreamSource(inputStream);
    transformer.transform(text, new StreamResult(writer));
    String finalString=writer.toString();
    System.err.println(“finalString– “+finalString);
    JSONObject xmlJSONObj = XML.toJSONObject(finalString);

    return xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
    }catch (Exception e) {
    e.printStackTrace();
    }
    return null;

    }

  27. Sumit Avatar
    Sumit

    Issue: How to single-child-xml-element-to-json-array using your xslt… what changes can I do in xslt to make this working

    For example for below XML:

    user1

    I want below json Output:

    “users”: {
    “user”: [
    “user1”
    ]
    }

    1. Bojan Bjelić Avatar

      Hi Sumit, the XML code is unfortunately not visible – could you edit your comment?

  28. kiran Avatar
    kiran

    hello Bojan Bjelić,
    Nice job , it works for me

  29. Rafael Avatar
    Rafael

    Hola Bojan,

    Muy buen trabajo, quiero saber cómo puedo obtener algunas etiquetas específicas; ejemplo, tengo el siguiente xml:

    EXT
    ITEL
    97560190326181214578
    20190326131210-0500
    air01tri
    89375368
    20190326131220-0500
    136
    COP
    573209196650
    COP
    10000000
    10000000
    2
    Navegacion 50MB + ChatWhatsapp Facebook Twitter por 24 horas-0-1
    123456789

    7111
    -2000.000000
    0.000000
    1
    20000

    Y quiero obtener únicamente el JSON del tag adjustmentRecordV2/dedicatedAccounts/adjustmentDedicatedAccountV2/adjustmentAmount, estoy haciendo unas modificaciones al xsl, pero obtengo todas las etiquetas que componen el tag adjustmentDedicatedAccountV2 vacíos, yo tengo multiples tags adjustmentAmount en diferentes tags adjustmentRecordV2/dedicatedAccounts/adjustmentDedicatedAccountV2/

    1. Bojan Bjelić Avatar

      Sorry but I don’t speak Spanish. Cheers, Bojan

  30. Brian Avatar
    Brian

    Hello Bojan,

    Came across your site while searching how to translate XML to Json, tried converting XML to Json using your XSLT. However the issue i have is that for certain XSLT converts xml array to Json array only when there are multiple xml elements of the same name. How do I ensure that XML array is always converted to Json array even when its one value/row.

    Cheers

    1. Bojan Bjelić Avatar

      Hi Brian, the XSLT was created with certain rules. It won’t create an array if it’s just one element. If you have specific requirements, please fork and alter it.

  31. Mukesh Kumar Avatar
    Mukesh Kumar

    Need below XML to be cinverted to json using XSLT
    XML
    ====
    GAZ 101 0002/59
    JSON
    =====
    “mediaFirstOptionalSkus”: [“op1″,”op2”],

    1. Bojan Bjelić Avatar

      Hi Mukesh, please check the examples in the article to see what fits you best.

  32. ANKIT TYAGI Avatar
    ANKIT TYAGI

    Hi Bjelic,

    Could you suggest me how to use saxon’s badgerfish in java spring boot for xml to json and json to xml.

    I have downloaded the latest maven of saxon.

    1. Bojan Bjelić Avatar

      Hi Ankit, the XSLT is independent of any framework, and intentionally so. I am not familiar with these – but if they support standard XSLT processing, it should work without any problems.

  33. Humera Shaikh Avatar
    Humera Shaikh

    Hi Bjelic,
    Do we have any snippet for conversion from JSON to XML in SFMC.
    Thanks

    1. Bojan Bjelić Avatar

      Hi, not really. Please share if you make one.
      Regards, Bojan

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.