
call transformation id_indent
on my JSON string, but that didn't work. So I set out to write my own JSON-pretty-printing XSL transformation, and that proved to be pretty easy, thanks to the transformation of JSON into JSON-XML built into call transformation
:<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" version="1.0">
<!--
Pretty-print JSON with ABAP XSLT
See http://help.sap.com/abapdocu_740/en/index.htm?file=abenabap_json_trafos.htm for the internal JSON-XML format
data(lv_in) = `{"Hello":"to the\nwhole \"World\"","I'm":51,"That's":true,"nothing":null,"one":{},"many":[null,false,42,"hi",{"a":"b"},[]]}`.
data lv_out type string.
call transformation zrha_pretty_json source xml lv_in result xml lv_out.
-->
<xsl:output encoding="UTF-8" method="text" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="object">
<xsl:param name="indent" select="''" />
<xsl:if test="position() > 1">
<xsl:value-of select="',& #xA;'"/>
</xsl:if>
<xsl:value-of select="$indent" />
<xsl:if test="@name">
<xsl:text>"</xsl:text>
<xsl:value-of select="@name" />
<xsl:text>": </xsl:text>
</xsl:if>
<xsl:text>{</xsl:text>
<xsl:if test="*">
<xsl:value-of select="'& #xA;'"/>
<xsl:apply-templates select="*">
<xsl:with-param name="indent" select="concat($indent,' ')" />
</xsl:apply-templates>
<xsl:value-of select="'& #xA;'"/>
<xsl:value-of select="$indent" />
</xsl:if>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template match="array">
<xsl:param name="indent" select="''" />
<xsl:if test="position() > 1">
<xsl:value-of select="',& #xA;'"/>
</xsl:if>
<xsl:value-of select="$indent" />
<xsl:if test="@name">
<xsl:text>"</xsl:text>
<xsl:value-of select="@name" />
<xsl:text>": </xsl:text>
</xsl:if>
<xsl:text>[</xsl:text>
<xsl:if test="*">
<xsl:value-of select="'& #xA;'"/>
<xsl:apply-templates select="*">
<xsl:with-param name="indent" select="concat($indent,' ')" />
</xsl:apply-templates>
<xsl:value-of select="'& #xA;'"/>
<xsl:value-of select="$indent" />
</xsl:if>
<xsl:text>]</xsl:text>
</xsl:template>
<xsl:template match="str">
<xsl:param name="indent" select="''" />
<xsl:if test="position() > 1">
<xsl:value-of select="',& #xA;'"/>
</xsl:if>
<xsl:value-of select="$indent" />
<xsl:if test="@name">
<xsl:text>"</xsl:text>
<xsl:value-of select="@name" />
<xsl:text>": </xsl:text>
</xsl:if>
<xsl:text>"</xsl:text>
<xsl:call-template name="escape">
<xsl:with-param name="string" select="."/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:template>
<xsl:template match="num|bool">
<xsl:param name="indent" select="''" />
<xsl:if test="position() > 1">
<xsl:value-of select="',& #xA;'"/>
</xsl:if>
<xsl:value-of select="$indent" />
<xsl:if test="@name">
<xsl:text>"</xsl:text>
<xsl:value-of select="@name" />
<xsl:text>": </xsl:text>
</xsl:if>
<xsl:value-of select="." />
</xsl:template>
<xsl:template match="null">
<xsl:param name="indent" select="''" />
<xsl:if test="position() > 1">
<xsl:value-of select="',& #xA;'"/>
</xsl:if>
<xsl:value-of select="$indent" />
<xsl:if test="@name">
<xsl:text>"</xsl:text>
<xsl:value-of select="@name" />
<xsl:text>": </xsl:text>
</xsl:if>
<xsl:text>null</xsl:text>
</xsl:template>
<xsl:template name="escape">
<xsl:param name="string"/>
<xsl:choose>
<xsl:when test="contains($string,'"')">
<xsl:call-template name="replace">
<xsl:with-param name="string" select="$string"/>
<xsl:with-param name="old" select="'"'"/>
<xsl:with-param name="new" select="'\"'"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($string,'\')">
<xsl:call-template name="replace">
<xsl:with-param name="string" select="$string"/>
<xsl:with-param name="old" select="'\'"/>
<xsl:with-param name="new" select="'\\'"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($string,'& #xA;')">
<xsl:call-template name="replace">
<xsl:with-param name="string" select="$string"/>
<xsl:with-param name="old" select="'& #xA;'"/>
<xsl:with-param name="new" select="'\n'"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($string,'& #xD;')">
<xsl:call-template name="replace">
<xsl:with-param name="string" select="$string"/>
<xsl:with-param name="old" select="'& #xD;'"/>
<xsl:with-param name="new" select="'\r'"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($string,'& #x9;')">
<xsl:call-template name="replace">
<xsl:with-param name="string" select="$string"/>
<xsl:with-param name="old" select="'& #x9;'"/>
<xsl:with-param name="new" select="'\t'"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="string"/>
<xsl:param name="old"/>
<xsl:param name="new"/>
<xsl:call-template name="escape">
<xsl:with-param name="string" select="substring-before($string,$old)"/>
</xsl:call-template>
<xsl:value-of select="$new"/>
<xsl:call-template name="escape">
<xsl:with-param name="string" select="substring-after($string,$old)"/>
</xsl:call-template>
</xsl:template>
</xsl:transform>
& #x
with &#x
in the source code above because I couldn't figure out how to dissuade this editor from doing multi-pass unencoding 😞
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
11 | |
8 | |
6 | |
5 | |
5 | |
5 | |
4 | |
4 | |
2 | |
2 |