2

I need to convert a JSON string to a XML string. The tags do contain attributes. From the answer in this topic I started using XSLT.

There exists a function fn:json-to-xml. I understand that it should convert the JSON into an XML without attributes(which I format using XSLT).

How do I use this function?

Because it's implemented in XSLT I would guess in the .xsl file, but I can't find any examples.

Many thanks in advance!

Community
  • 1
  • 1
DA--
  • 723
  • 1
  • 8
  • 20

2 Answers2

7

The function is defined in XSLT 3.0, in XPath 3.1, and in XQuery 3.1.

The simplest way to use it is probably to install Saxon-HE 9.7.0.7 and then run it from XQuery on the command line like this:

java -cp /dddd/9.7.0.7/he/saxon9he.jar net.sf.saxon.Query -t -qs:"json-to-xml(unparsed-text('/eeee/test.json'))" -o:output.xml
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • 1
    That's already something I couldn't find as an example online. But how can I embed this in my JAVA code or .xsl file? Can I replace _unparsed-text('/eeee/test.json')_ by the json-string as suggested in the [documentation](http://www.saxonica.com/html/documentation/functions/fn/json-to-xml.html)? – DA-- Aug 09 '16 at 09:07
  • For calling Saxon XQuery from Java, see the documentation here: http://www.saxonica.com/documentation/index.html#!using-xquery/api-query/s9api-query You can of course use `json-to-xml($param)` and pass the value of $param (a string in JSON format) as a parameter to the query. – Michael Kay Aug 09 '16 at 11:55
  • "That's already something I couldn't find as an example online". Googling for someone who has done exactly what you want to do is not a very efficient approach to programming. Much better to learn the concepts of the tools you are using so you can adapt the examples to new problems. – Michael Kay Aug 09 '16 at 11:59
  • 1
    I agree and that's definitely how I work. But for someone new to the Java/XML/XSLT it's a hard to distinguish what comes where in the code. Thank you for the additional reference to XQuery documentation, I'm sure it will be helpful to other starters as well. – DA-- Aug 09 '16 at 12:10
2

Here is a simple example taken from the XSLT 3.0 spec https://www.w3.org/TR/xslt-30/#func-json-to-xml, the sample input can be any string in the JSON format, below I use an XML document containing a data element with JSON:

<root>
    <data>{
        "desc"    : "Distances between several cities, in kilometers.",
        "updated" : "2014-02-04T18:50:45",
        "uptodate": true,
        "author"  : null,
        "cities"  : {
        "Brussels": [
        {"to": "London",    "distance": 322},
        {"to": "Paris",     "distance": 265},
        {"to": "Amsterdam", "distance": 173}
        ],
        "London": [
        {"to": "Brussels",  "distance": 322},
        {"to": "Paris",     "distance": 344},
        {"to": "Amsterdam", "distance": 358}
        ],
        "Paris": [
        {"to": "Brussels",  "distance": 265},
        {"to": "London",    "distance": 344},
        {"to": "Amsterdam", "distance": 431}
        ],
        "Amsterdam": [
        {"to": "Brussels",  "distance": 173},
        {"to": "London",    "distance": 358},
        {"to": "Paris",     "distance": 431}
        ]
        }
        }</data>
</root>

The template for the data element then simply calls json-to-xml(.) and the whole stylesheet to demonstrate the result outputs the returned XML:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    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>

The output with Saxon 9.7 HE is

        <map xmlns="http://www.w3.org/2005/xpath-functions">
   <string key="desc">Distances between several cities, in kilometers.</string>
   <string key="updated">2014-02-04T18:50:45</string>
   <boolean key="uptodate">true</boolean>
   <null key="author"/>
   <map key="cities">
      <array key="Brussels">
         <map>
            <string key="to">London</string>
            <number key="distance">322</number>
         </map>
         <map>
            <string key="to">Paris</string>
            <number key="distance">265</number>
         </map>
         <map>
            <string key="to">Amsterdam</string>
            <number key="distance">173</number>
         </map>
      </array>
      <array key="London">
         <map>
            <string key="to">Brussels</string>
            <number key="distance">322</number>
         </map>
         <map>
            <string key="to">Paris</string>
            <number key="distance">344</number>
         </map>
         <map>
            <string key="to">Amsterdam</string>
            <number key="distance">358</number>
         </map>
      </array>
      <array key="Paris">
         <map>
            <string key="to">Brussels</string>
            <number key="distance">265</number>
         </map>
         <map>
            <string key="to">London</string>
            <number key="distance">344</number>
         </map>
         <map>
            <string key="to">Amsterdam</string>
            <number key="distance">431</number>
         </map>
      </array>
      <array key="Amsterdam">
         <map>
            <string key="to">Brussels</string>
            <number key="distance">173</number>
         </map>
         <map>
            <string key="to">London</string>
            <number key="distance">358</number>
         </map>
         <map>
            <string key="to">Paris</string>
            <number key="distance">431</number>
         </map>
      </array>
   </map>
</map>

So as with any other function taking an input as as xs:string you can of course pass in any string value you have in your XSLT or XPath code or you can pass in a node which is then atomized to a string first.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • 1
    Great, thanks for summarizing these steps for me. One last point to clearify, does the JSON need to be enclosed by a tag(the example uses ? Or can it be plain JSON, and how would the this statement change __ __ __? – DA-- Aug 09 '16 at 09:57
  • How about editing your question and explaining exactly where/how do you have your JSON? You asked for an example using XSLT and the normal input to XSLT is XML so I have presented an example having the JSON inside of an XML element. But of course you can use that function on any string value you have, for instance, as Michael Kay has already shown you, by reading in a JSON file with `unparsed-text('file.json')`. Or by passing a parameter with a string containing the JSON to the XSLT. The function is, like most functions in programming languages, not restricted to a particular context. – Martin Honnen Aug 09 '16 at 10:06
  • OK, I made a (modest) modification to the question. Thank you for the additional comments. – DA-- Aug 09 '16 at 10:11
  • Thanks for this answer Martin. I have one question. After generating the xml i want to convert it back to json again using xml-to-json() function. I am not getting result in same json format. How can i get the same json back from the output xml? – Pradeep Singh Feb 23 '18 at 11:29
  • @PradeepSingh, please ask a new question of your own, explaining what you are trying to achieve with some sample of XML and JSON. – Martin Honnen Feb 23 '18 at 11:31