On 15.03.2019 11:42, Mukul Gandhi gandhi(_dot_)mukul(_at_)gmail(_dot_)com wrote:
Hi all,
     XPath 3.1 has functions json-to-xml() and xml-to-json(). I thought 
of using these two functions in a XSLT 3.0 stylesheet, to do json to 
json transformations. Below is an example of this,
Input JSON file person.txt:
{
    "id" : 105,
    "medals" : [1, 2, 3],
    "fName" : "Mukul",
    "lName" : "Gandhi",
    "address" : {
       "street1" : "xyz",
       "street2" : "maddison avenue",
       "country" : "C1"
     }
}
I wish to transform above JSON document, into another JSON document 
which should look like following,
{
    "id" : 105,
    "medals" : [1, 2, 3],
    "name" : "Mukul Gandhi",
    "address" : {
       "street1" : "xyz",
       "street2" : "maddison avenue",
       "country" : "C1"
     }
}
Everything in second JSON document is same as the first one, except that 
"fName" and "lName" fields have been merged into one "name" field. 
Following is a XSLT stylesheet I've written for the mentioned requirements,
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                          xmlns:xs="http://www.w3.org/2001/XMLSchema"
                          xmlns:fn="http://www.w3.org/2005/xpath-functions"
                          exclude-result-prefixes="xs fn"
                          version="3.0">
     <xsl:variable name="inpJson" select="unparsed-text('person.txt')" 
as="xs:string"/>
     <xsl:output method="text" />
     <xsl:template match="/">
        <xsl:variable name="inpXml" select="json-to-xml($inpJson)"/>
        <xsl:variable name="intermediate">
           <xsl:apply-templates select="$inpXml/fn:map" mode="M0"/>
        </xsl:variable>
        <xsl:copy-of select="xml-to-json($intermediate, map{'indent': 
true()})"/>
     </xsl:template>
     <xsl:template match="node() | @*" mode="M0">
         <xsl:copy>
             <xsl:apply-templates select="node() | @*" mode="M0"/>
         </xsl:copy>
     </xsl:template>
     <xsl:template match="fn:string[@key = 'fName']" mode="M0">
        <fn:string key="name"><xsl:value-of select="concat(., ' ', 
following-sibling::fn:string[1])"/></fn:string>
     </xsl:template>
     <xsl:template match="fn:string[@key = 'lName']" mode="M0"/>
</xsl:stylesheet>
The above mentioned stylesheet, produces the wanted results.
Just thought of sharing these facts with members here, for any comments, 
suggestions.
Given XSLT 3, you can simply declare
   <xsl:mode name="M0" on-no-match="shallow-copy"/>
instead of the identity transformation template you have set up for that 
mode.
And you can shorten the code using other XSLT/XPath 3 constructs like 
using the string concatenation operator
   . || ' ' || following-sibling::fn:string[1])
instead of concat.
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--