Search

In XSLT, everything is about stealth. Stealth of power, that is. No wonder that one of the most confusing yet most powerful manipulation templates around applies the so-called “Ninja Technique”+.

+Origins of this term are unclear, althoug it is widely believed that it first appeared in Japan in the 14th century.

This technique, much like the Sandpeople, who travel in a single file to hide their numbers, makes heavy use of the same few lines of code, over and over again, called a recursion.

For beginners hard to grasp, the power of this technique becomes soon clear to the brave. Especially when you compare the ninja starter to monsters like this.

Both do basically the same (apply exactly the same transformations again and again recursively on a nodeset), yet the ninjas managed to conceal their true power.

It was until today, that seemingly nobody cared to do the obvious: use this centuries old technique to transform XML into JSON, as both share very similar nesting structures.

I proudly present: My first actually useful XSLT-Util: XML to JSON.

One of the key-features comes with the use of the previous mentioned techique: It will transform anything, no matter how many nested levels.

This of course requires you to do transformations on you XML before handing it over to the template.

The basic call goes like this:

<xsl:call-template name="json">
    <xsl:with-param name="xml">
            <any>
                <xml />
                <something like="this" />
            </any>
    </xsl:with-param>
</xsl:call-template>

Nothing special here (although I have to let you know, better earlier than later: attributes will not get transformed!). However, it gets much more interesting when you do actual XSLT within the <xsl:with-param>:

<xsl:call-template name="json">
    <xsl:with-param name="xml">
            <employees>
            <xsl:for-each select="company/employees">
                <entry>
                    <name><xsl:value-of select="name" /></name>
                    <age><xsl:value-of select="age" /></age>
                </entry>
            </xsl:for-each>
            </employees>
    </xsl:with-param>
</xsl:call-template>

This will strip out all the unnecessary elements, reducing the returned JSON-object to exactly what you need to pass on to your JavaScript.

In order for it to do those XML-transformations as a parameter, you need to have EXSLT installed. And to escape quotes in the result, you need the String Replace Util too.

I must admit, the code and the returned JSON objects are a bit… messy. And the whole attribute-issue has yet to be cleared. But its a start and I desperately wanted to get this out (hence the crazy-talk).

Truly great work Phoque. Can’t wait for someone to build in the ability to handle attributes!

Wow.. this is great!

(the ending employees-tag is missing in the last example.)

(the ending employees-tag is missing in the last example.)

No no, it only accepts broken XML. Thanks for the heads up :-)

Nice work phoque! I’m looking forward to giving it a run.

+2million awesome points phoque — this is sweet.

I presume it will also work as follows?

<xsl:call-template name="json">
    <xsl:with-param name="xml" select="/data/my-data-source"/>
</xsl:call-template>

I presume it will also work as follows?

Technically, it does. However there are some problems with HTML embedded into elements (these HTML elements trigger a recursion).

Ah yes, hmm. Perhaps you could have an optional blacklist of HTML block-level tag names (p, blockquote, div etc.). By default these are ignored for the recursion and are used as values rather than nodes. But passing a ignore-html value of true to the template would bypass this filter and recurse (in case this was desired functionality).

Or, assuming HTML was always within a Textarea, check if the element has a word-count attribute and ignore HTML inside that element.

Kind of makes it Symphony-specific rather than generic XSLT though.

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