XLST is professional HTML

You keep going on an on about “full-concept-separation” but it’s not really clear how can you have a dynamic HTML without having any code in it

You’re right, I’m not sure how you can generate HTML without any code, but let me suggest you XSLT (eXtensible StyLesheets Transformation) as a way to take XML-based data and transform it to HTML. You know, forget XML let’s take JSON (Javascript Object Native). how, you ask? very simple – just add json2xml() function at the entrance of your xml2html() function and your set

function json2html (jsObject) {
    return xml2html(json2xml(jsObject));

how will the xml2html() function looks like? oh, it’s very simple: you simply take the XML object and the XSLT template, throw them both together into a XSLT-processor and return the resulted HTML

xslt = new XSLTProcessor();

xsltDocument = xslt.readXsltFile(__dirname + “/themes/"+config.theme+"/xslt/default.xsl")

function xml2html() {
    var xmlDocument = xslt.readXmlString("<xml>"+ self.json2xml (content) +"</xml>");
    return xslt.transform( xsltDocument,xmlDocument, []);

you may also notice I pulled another trick here, choosing my theme by selecting the proper xslt (and therefore resulting HTML) at this form.

OK, but why use XSLT, what’s the big “hoo-haa” about it?

compatibility. you can use with to create HTML in any language that has an XSLTProcessor and more than that – you can run it on the server side as well as on the browser. You can use it to support multiple languages and apply permissions. I’ll show you how:

You probably noticed my XSLTDocuemnt is default.xsl. This doesn’t mean it’s the only file I have. I like to separate them easier management but this primary file has import commands for the rest of the templates.

<xsl:import href="common.xsl" />

Next, this default template has all the strings I will need. Meaning that I can switch my language by selecting a different template.

Let’s see a piece of code to define a string as a parameter and then use it:

<xsl:param name="btn_signin" select=“‘’Sign in”/>
<a id="btn_signin" href=“/signin">
    <xsl:value-of select="$btn_signin" />

having the <xsl: /> tags processed by the XSLTProcessor, the resulting HTML would be:

<a id="btn_signin" href=“/signin">Sign in</a>

The strings can (and should) be simple short string, like the one we’ve just seen, but they can also be short pieces of HTML code. For example, the entire terms of use list can be issued as a single string, despite having html tags in it:

<xsl:param name="terms_of_use">
        <li>Don’t endorse violence</li>
        <li>Don’t spam or solicit irrelevant content/li>
        <li>Don’t infringe copyright usage</li>
        <li>The user is the sole responsible for its published content</li>

Now let’s see how we can manage permissions. Please note that we can set which buttons is displayed and which isn’t but we don’t have control over what is sent to the server. this is critical: never-ever assume that you have control over what’s going on in the browser – even if your client-side code is minified and uglified and the transactions are encrypted, a nasty hacker still might send a command to the server that you didn’t expect would be possible. permissions should be carefully looked after in the request-processing as well. Back to permissions in XSLT. let’s decide that each json-to-be-html we send will also include the list of permissions for actions the user is allowed to performs

var jsonObj = {
    “topics” : { “topic” : topicsArray },
                 “permissions” : {“endorse”:true, “comment”:true}

A small note on the topics > topic structure that might look a bit redundant, but actually it used for the array’s element -tag as you can see in the the expected XML structure is as follows –

    <topic> … topic attribute … </topic>

you may notice that the permissions set doesn’t require <permission> tag because it’s a set and each element has its own name. in the XSLT template we will use it with a conditional that will display the “Endorse” link only if the user have the permission:

<xsl:if test=“//permissions/endorse”>
    <a href=“/topics/{topic_id}/endorse”><xsl:value-of select=“$btn_endorse” /></a>

note the “//“ in the permission query, used to find ANY “//permissions/endorse” in the XML, and not limiting the search to the current node we’re inspecting (which is a specific topic, in our example).

Wait! conditionals? is XSLT a language? I thought it’s just xml and HTML stuff

Yes, and no. XLT is written in XML using tags (you know <tag> …. </tag>) but it has a little bit of coding capabilities in each, making it powerful just enough. I’ll already showed you the xsl:if but I’ll give a few more examples:

the most important xsl tag is xsl:apply-templates that will process all the child-nodes of the current tag and add their respective template. The following code will apply for any XML input for its root level causing the chain reaction to process the entire XMLdocument (assuming of course that each template will apply the templates of its child-nodes)

<xsl:template match="/">
    <xsl:apply-templates />

the xsl:template is actually the template to be match to the entity you wish to print, and it’s XPATH so you can write sophisticated rules to it like <xsl:template match=“page[@type=‘topic”]”> which will apply on page tags with a type attribute having a “topic” as a value.

the xsl:choose allows to create more complicated if then else conditions:

    <xsl:when test=“//permissions/suggest> do something  </xsl:when>
    <xsl:when test=“//user/admin> do something else </xsl:when>
    <xsl:otherwise> default in case all other tests failed</xsl:otherwise>

the xsl:for-each is a basic loop running on a list of items. Most cases you can simply <xsl-apply-templates match=“item” /> instead but running the for-each loop will keep you on the current score which might contain useful information

<xsl:for-each select="tags/tag">
        <span style="background-color:{color}">&nbsp;</span>
        <xsl:value-of select="current()" />

And that more-or-less all the different XSLT tags I use. I recommend going over the tutorials for both path and xslt at www.w3schools.com for more comprehensive knowledge.

Wait a minute! really? is that all the functionality you use? don’t you have any really complex feature there?

You are right, actually I do have two things that are a bit smarter than that. First, I have the error message mechanism. all my error strings are bunched to a single data-set and there’s a nifty function to pull the appropriate message

<xsl:variable name="errorMessages">

<error type=“no-permission">You do not have permissions for this action</error>
<error type=“unknown_error">Unknown error</error>

<xsl:template match="message[@type='error"]">
    <xsl:variable name="vSelector" select="@message"/>
    <xsl:variable name="errorMessage" select=“exslt:node-set($errorMessages)/*[@type=$vSelector]”/>
    <xsl:if test="count(exslt:node-set($errorMessages)/*[@type=$vSelector]) &gt; 0">
        <xsl:value-of select="$errorMessage"/>

So we have a variable holding list of tags (notice it’s a variable and not a parameter as before),

I’m using a free 3rd-party external library (http://exslt.org/common) to extract the right item from the variable according to the input and display the message, this way the variable can contain additional information on the error that will be used where the error message is displayed, without the need to get it as an input.

Another trick I pull uses the same technique to display pretty-dates (like “2 hours ago”)

<xsl:variable name="timestamps">
    <timeLabel id=“just-now">Just now</timeLabel>
    <timeLabel id=“a-minute-ago">A minute ago</timeLabel>
    <timeLabel id=“#-minutes-ago”># minutes ago</timeLabel>

<xsl:variable name="vSelector" select="created/pattern"/>
<xsl:variable name="prettyCreated">
<xsl:call-template name="string-replace-all">
    <xsl:with-param name="text" select="exslt:node-set($timestamps)/*[@id=$vSelector]" />
    <xsl:with-param name="replace" select="'#'" />
    <xsl:with-param name="by" select="created/patternValue" />

<time datetime="{created/timestamp}" title=“{created/formatted}">
    <xsl:value-of select="$prettyCreated" />

you may notice in case of number of minutes, I have a single field with a hashtag, meaning the XSLTProcessor will need to replace the hashtag with a real number. so now, not only we find the real variable-sub-element we also search-and-replace (again with the ex-xslt library) the hash tag with the real value, being passed as one of the parameters of the “created” tag.

OK, I got it. Last question before we drop this issue forever – who do you suppose should write the XSLT code?

ok, you got me there – the guy who’ll build your HTML. It can either be your web-developer or your web-designer as XSLT, just like HTML, falls right in the middle of these categories. It’s like the DMZ where there’s no substantial code but no real design (that should be in the CSS, mind you), so both parties can more-or-less understand it. You can see that XSLT as the advanced version of HTML, boosting it with function-like capabilities, variables, loops and conditionals.

A final note, though, most of the XSLT libraries I’ve worked with (and I tried several) were published circa 2008. Generally it seems not so many people today use it today although I couldn’t find any rant on it. My guess is that it didn’t reach any large audience enough to be in the mainstream simply because developers would prefer to use their own language-specific templates.

I encourage the use of XSLT. I think it’s a good technology. This post was designed just to give few highlights so if you care to read more, I recommend http://www.w3schools.com/xsl/ for a start.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: