Search

A new XSLT utility, “XML to JSON” is now available for download. Comments and feedback can be left here but if you discover any issues, please post it on the issue tracker.

@phoque awesome.

Thanks for this, I want to use it but am having trouble implementing it. I am new to Symphony : Do I load this as a utility? how do I call it from a template? I’d like to have a template that just spits out whatever data I feed it thru a “data-source” into JSON format, is that possible?

Thanks much! Kirk

Try

<xsl:call-template name="json">
    <xsl:with-param name="xml">
        <xsl:copy-of select="/data/datasource" />
    </xsl:with-param>
</xsl:template>

You can use anything you like (for-each, apply-templates…) instead of <xsl:copy-of select="/data/datasource" />

@phoque This utility generates some weird spaces. You can fix it using xsl:text element.

I added formatting to this utility. W/o formatting, debugging an errored JSON is a pain ... Here's a formatted example.

Here's the code:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    xmlns:string="http://getsymphony.com/functions"
    extension-element-prefixes="exsl string">




<xsl:strip-space elements="*"/>




<!--
 Example call

     <xsl:call-template name="json">
         <xsl:with-param name="xml">
             [Any XSLT-transformation]
         </xsl:with-param>
     </xsl:call-template>

Apply formatting to output:

     <xsl:call-template name="json">
         <xsl:with-param name="format" select="true()"/>
         <xsl:with-param name="xml">
             [Any XSLT-transformation]
         </xsl:with-param>
     </xsl:call-template>
 -->

<xsl:template name="xml-to-json">
    <xsl:param name="format" select="false()"/>
    <xsl:param name="format-tab" select="'&#09;'"/>
    <xsl:param name="xml"/>

    <xsl:text>&#10;{&#10;</xsl:text>
    <xsl:apply-templates select="exsl:node-set($xml)" mode="json">
        <xsl:with-param name="format" select="$format"/>
        <xsl:with-param name="format-tab" select="$format-tab"/>
    </xsl:apply-templates>
    <xsl:text>&#10;}</xsl:text>
</xsl:template>




<xsl:template match="*" mode="json">
    <xsl:param name="format"/>
    <xsl:param name="format-tab"/>

    <xsl:variable name="has-siblings" select="name(.) = name(preceding-sibling::*) or name(.) = name(following-sibling::*)"/>
    <xsl:variable name="has-children" select="child::*"/>
    <xsl:variable name="is-node" select="$has-siblings and position() = 1 or not($has-siblings)"/>


    <xsl:if test="$format">
        <xsl:apply-templates select="ancestor::*[1]" mode="json-format">
            <xsl:with-param name="format-tab" select="$format-tab"/>
        </xsl:apply-templates>
    </xsl:if>


    <!-- Name -->
    <xsl:if test="$is-node">
        <xsl:text>"</xsl:text>
        <xsl:value-of select="name(.)"/>
        <xsl:text>":</xsl:text>
    </xsl:if>


    <!-- Array -->
    <xsl:if test="$has-siblings and position() = 1">
        <xsl:text>[</xsl:text>

        <xsl:if test="$format">
            <xsl:text>&#10;</xsl:text>
            <xsl:value-of select="$format-tab"/>
        </xsl:if>
    </xsl:if>

    <xsl:if test="$has-siblings and $format">
        <xsl:value-of select="$format-tab"/>
    </xsl:if>


    <!-- Object -->
    <xsl:if test="$has-children">
        <xsl:text>{</xsl:text>

        <xsl:if test="$format">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:if>


    <!-- Recursion -->
    <xsl:apply-templates select="* | text()" mode="json">
        <xsl:with-param name="format" select="$format"/>
        <xsl:with-param name="format-tab" select="$format-tab"/>
    </xsl:apply-templates>


    <!-- Empty Element -->
    <xsl:if test=". = ''">null</xsl:if>


    <!-- /Object -->
    <xsl:if test="$has-children">
        <xsl:if test="$format">
            <xsl:text>&#10;</xsl:text>

            <xsl:apply-templates select="ancestor::*[1]" mode="json-format">
                <xsl:with-param name="format-tab" select="$format-tab"/>
            </xsl:apply-templates>
        </xsl:if>

        <xsl:text>}</xsl:text>
    </xsl:if>


    <!-- /Array -->
    <xsl:if test="$has-siblings and position() = last()">
        <xsl:text>&#10;</xsl:text>

        <xsl:if test="$format">
            <xsl:apply-templates select="ancestor::*[1]" mode="json-format">
                <xsl:with-param name="format-tab" select="$format-tab"/>
            </xsl:apply-templates>
        </xsl:if>

        <xsl:text>]</xsl:text>
    </xsl:if>


    <!-- Separator -->
    <xsl:if test="position() != last()">
        <xsl:text>,</xsl:text>

        <xsl:if test="$format">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:if>
</xsl:template>




<xsl:template match="text()" mode="json">
    <xsl:variable name="is-string" select="string(number(.)) = 'NaN' and . != 'true' and . != 'false'"/>

    <xsl:if test="$is-string">"</xsl:if>
    <xsl:call-template name="string-replace">
        <xsl:with-param name="haystack" select="." />
        <xsl:with-param name="search" select="'&#34;'" />
        <xsl:with-param name="replace" select="'&#92;&#34;'" />
    </xsl:call-template>
    <!-- Escape Quotes -->
    <xsl:if test="$is-string">"</xsl:if>
</xsl:template>




<xsl:template match="*" mode="json-format">
    <xsl:param name="format-tab"/>

    <xsl:value-of select="$format-tab"/>

    <xsl:apply-templates select="ancestor::*[1]" mode="json-format">
        <xsl:with-param name="format-tab" select="$format-tab"/>
    </xsl:apply-templates>
</xsl:template>




</xsl:stylesheet>

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details