1

I am able to transform JSON to XML using XSLT 3.0. When transforming to XML fields the data in subjects are missing the XML structure.

{
  "student" : "john",
  "class" : "Bachelors",
  "subjects" : "<college><subject><subjects>maths</subjects><term>spring</term></subject></college>"
}

XSLT :

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/> 
  <xsl:strip-space elements="*"/>
  <xsl:param name="jsonText"/>

  <xsl:template match="@*|node()"> 
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template> 

  <xsl:template name="init">
    <xsl:apply-templates select="json-to-xml($jsonText)"/> 
  </xsl:template>
</xsl:stylesheet>`

Java Code :

public static void main(String[] args){
    final String XSLT_PATH = "src/so/test1/json2xml.xsl";
    final String JSON = ""{\n" +"    \"student\": \"john\",\n" +
    "    \"class\": \"Bachelors\"\n" +
    "    \"subjects\": \"<college><subject><subjects>maths</subjects><term>spring</term></subject></college>"\n"
                "}";

    OutputStream outputStream = System.out;    
    Processor processor = new Processor(false);    
    Serializer serializer = processor.newSerializer();
    serializer.setOutputStream(outputStream);    
    XsltCompiler compiler = processor.newXsltCompiler();
    XsltExecutable executable = compiler.compile(new StreamSource(new File(XSLT_PATH)));    
    XsltTransformer transformer = executable.load();
    transformer.setInitialTemplate(new QName("init")); 
    transformer.setParameter(new QName("jsonText"), new 
 XdmAtomicValue(JSON));
    transformer.setDestination(serializer);
    transformer.transform();
}

Error:

Error at char 12 in xsl:apply-templates/@select on line 8 column 58 of json2xml.xsl:
  FOJS0001: Invalid JSON input: Unescaped control character (xd)
Exception in thread "main" net.sf.saxon.s9api.SaxonApiException: Invalid JSON input: Unescaped control character (xd)
      at net.sf.saxon.s9api.XsltTransformer.transform(XsltTransformer.java:599)
      at com.xmltojson.sampleclass.SimpleJaxp.main(SimpleJaxp.java:49)
Caused by: net.sf.saxon.trans.XPathException: Invalid JSON input: Unescaped control character (xd)
4
  • I don't think ""{\n" compiles. So you might want to take your time to prepare a minimal but complete and well-formatted code sample that allows others to reproduce the problem. And perhaps even start a new question if running Saxon with Java is the problem, the first sentence still reads "When transforming to XML fields the data in subjects are missing the XML structure" and if an answer to that is given it is rather strange to edit the question to ask about a new problem. Commented Jul 24, 2017 at 19:20
  • 1
    You are doing a horrible job formatting your code snippets. I have edited my answer with some Java code that works fine for me with Saxon 9.8 HE. Commented Jul 24, 2017 at 20:29
  • @MartinHonnen Thank you, can i use the same piece of Java code to transform from XML to JSON. Commented Jul 25, 2017 at 13:19
  • Please ask a new question if you can't figure it out, I would expect that using <xsl:output method="json"/> or <xsl:output method="adaptive"/> in the XSLT should suffice if you your stylesheet returns a map or an array. Commented Jul 25, 2017 at 13:36

1 Answer 1

2

Add a template

<xsl:template match="string[@key = 'subjects']" xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:sequence select="parse-xml(.)/node()"/>
  </xsl:copy>
</xsl:template>

to make sure the string data is parsed to XML.

Note that using XSLT 3.0 you can use <xsl:mode on-no-match="shallow-copy"/> instead of having to spell out the identity transformation.

A quick example is

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="jsonText"><![CDATA[{
    "student" : "john",
    "class" : "Bachelors",
    "subjects" : "<college><subject><subjects>maths</subjects><term>spring</term></subject></college>"
    }]]></xsl:param>
    <xsl:mode on-no-match="shallow-copy"/>
    <xsl:template name="init">
        <xsl:apply-templates select="json-to-xml($jsonText)"/>
    </xsl:template>

    <xsl:template match="string[@key = 'subjects']" xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:sequence select="parse-xml(.)/node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

which (when run with Saxon 9.8.0.3 HE with it:init) outputs

<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.w3.org/2005/xpath-functions">
   <string key="student">john</string>
   <string key="class">Bachelors</string>
   <string key="subjects">
      <college xmlns="">
         <subject>
            <subjects>maths</subjects>
            <term>spring</term>
         </subject>
      </college>
   </string>
</map>

Here is a complete Java program based on your code snippets posted in various edits:

import java.io.File;
import java.io.OutputStream;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
import net.sf.saxon.s9api.XdmAtomicValue;
import net.sf.saxon.s9api.XsltCompiler;
import net.sf.saxon.s9api.XsltExecutable;
import net.sf.saxon.s9api.XsltTransformer;

public class Saxon98HETest1 {

    public static void main(String[] args) throws SaxonApiException {
        final String XSLT_PATH = "sheet1.xsl";
        String JSON = "{\n" +
"  \"student\" : \"john\",\n" +
"  \"class\" : \"Bachelors\",\n" +
"  \"subjects\" : \"<college><subject><subjects>maths</subjects><term>spring</term></subject></college>\"\n" +
"}";
        testJsonToXml(XSLT_PATH, JSON);
        System.out.println();

        JSON = "{\n" +
                            "    \"color\": \"red\",\n" +
                            "    \"value\": \"#f00\"\n" +
                            "}";
        testJsonToXml(XSLT_PATH, JSON);
        System.out.println();
    }

    static void testJsonToXml(String xsl, String json) throws SaxonApiException {
        OutputStream outputStream = System.out;
        Processor processor = new Processor(false);
        Serializer serializer = processor.newSerializer();
        serializer.setOutputStream(outputStream);
        XsltCompiler compiler = processor.newXsltCompiler();
        XsltExecutable executable = compiler.compile(new StreamSource(new File(xsl)));
        XsltTransformer transformer = executable.load();
        transformer.setInitialTemplate(new QName("init"));
        transformer.setParameter(new QName("jsonText"), new XdmAtomicValue(json));
        transformer.setDestination(serializer);
        transformer.transform();       
    }

}

When compiled and run against Saxon 9.8.0.3 HE I get the output

<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.w3.org/2005/xpath-functions">
   <string key="student">john</string>
   <string key="class">Bachelors</string>
   <string key="subjects">
      <college xmlns="">
         <subject>
            <subjects>maths</subjects>
            <term>spring</term>
         </subject>
      </college>
   </string>
</map>

<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.w3.org/2005/xpath-functions">
   <string key="color">red</string>
   <string key="value">#f00</string>
</map>

and no errors. The stylesheet is as shown above, without the preset param content:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="jsonText"></xsl:param>
    <xsl:mode on-no-match="shallow-copy"/>
    <xsl:template name="init">
        <xsl:apply-templates select="json-to-xml($jsonText)"/>
    </xsl:template>

    <xsl:template match="string[@key = 'subjects']" xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:sequence select="parse-xml(.)/node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

4 Comments

@bookofcodes, can you edit your question and show a minimal but complete code sample together with the exact error message and precise information of the software you use to run the code?
i have edited the question i am trying to use the above code using java.
Please add the exact error message and the information about which line of Java gives you that error. And why is String JSON = " ", I thought you have a certain JSON input and not some string with white space.
I have tried to throw together some Java code using my stylesheet together with JSON inputs (taken from your various edits) as Java strings. Works fine for me.

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.