2

I am new to XSLT, I have a simple JSON which I want to transform to an XML using XSLT 3.0. I tried parsejson and jsontoxml functions as per w3c recommendations, but produced output is not in desired format. I am using Saxonica processor for the purpose. Is it possible to write a single xslt which can be used in any given json of a particular structure irrespective of key names. Otherwise how can I approach to convert a json to desired xml using xslt features

I tried the example in the answer: [JSON to XML transformation in XSLT 3.0, but is not working for me

Input JSON

<data>{

      "Assets": [
  { "Asset": {        
        "Open": "25.15",
        "High": "25.15",
        "Low": "25.11",
        "Close": "25.87"
      }},
      { "Asset": {        
        "Open": "25.15",
        "High": "25.15",
        "Low": "25.11",
        "Close": "25.87"
      }}]

}
</data>

Expected Output

<data>
   <Assets>
      <Asset>
         <Close>25.87</Close>
         <High>25.15</High>
         <Low>25.11</Low>
         <Open>25.15</Open>
      </Asset>
      <Asset>
         <Close>25.87</Close>
         <High>25.15</High>
         <Low>25.11</Low>
         <Open>25.15</Open>
      </Asset>
   </Assets>
</data>

Actual output I got using my xslt

<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.w3.org/2005/xpath-functions">
   <array key="Assets">
      <map>
         <map key="Asset">
            <string key="Open">25.15</string>
            <string key="High">25.15</string>
            <string key="Low">25.11</string>
            <string key="Close">25.87</string>
         </map>
      </map>
      <map>
         <map key="Asset">
            <string key="Open">25.15</string>
            <string key="High">25.15</string>
            <string key="Low">25.11</string>
            <string key="Close">25.87</string>
         </map>
      </map>
   </array>
</map>

My XSLT function

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs math" version="3.0">
   <xsl:output indent="yes" />
   <xsl:template match="data">
      <xsl:copy-of select="json-to-xml(.)" />
   </xsl:template>
</xsl:stylesheet>

Below is the sample code I am using with saxon to do transformation

        var xslt = new FileInfo("myxslt.xslt");
        var input = new FileInfo("inputxml.xml");

        // Compile stylesheet
        var processor = new Processor(true);
        var compiler = processor.NewXsltCompiler();
        var executable = compiler.Compile(new Uri(xslt.FullName));
        Serializer serializer = processor.NewSerializer();
        serializer.SetOutputFile(txtOutput.Text);

        // Do transformation to a destination
        var destination = new XdmDestination();
        using (var inputStream = input.OpenRead())
        {
            var transformer = executable.Load();
            transformer.SetInputStream(inputStream, new Uri(input.DirectoryName));
            transformer.Run(serializer);
        }
2
  • 1
    Well, the problem is that {"key 1" : 1} as JSON with your desired format would result in an element name key 1 which is not an allowed name. That is why the format the json-to-xml function returns puts the JSON property name into an attribute. So while writing a transformation from the XML you currently get to the one you want is trivial for your presented input it is not clear what result you want in general. Commented Dec 1, 2017 at 9:52
  • @MartinHonnen: Thanks for the answer and note about space in key. I think I will have to handle that before passing json to xslt processor. Am I right? Commented Dec 1, 2017 at 11:12

1 Answer 1

6

It is trivial to solve that for your given input with

<xsl:template match="data">
    <xsl:copy>
        <xsl:apply-templates select="json-to-xml(.)/*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[@key]" xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
    <xsl:element name="{@key}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

however using JSON property names with spaces or colons or other characters not allowed in XML element names would break that approach easily.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot. It is exactly what I wanted. I wanted to convert JSON to xml and apply further xslt functions to manipulate data to create a flat xml.
You might need additional rules, for example, to handle nested arrays: the key thing is that there's no single universal way of representing such structures in XML, so you have to make your own choices.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.