The Death of XSLT in Web Frameworks
Join the DZone community and get the full member experience.
Join For FreeActually I've never used it on myself, but I liked the idea at that time. It seemed to be clear and powerful. Funny that only now I have a chance to check how it works in practice. And at least now I know why this approach failed.
For two weeks, I'm outsourced to help some company in their web project. They use their own, home-made web framework for this, to talk to their own, home-made document-repository system. Unfortunately, both seemed to be buggy and unstable, though they say that's not the first project they use them in (I can't believe it's true, really). I guess they would be better off using standard Java Content Repository (JSR-170) for implementing documents repository, and some modern web framework instead of their own home-grown one. If they insisted on XML/XSLT transformations, they could use Cocoon. At least there would be more documentation available, and it would be well-tested and stable. But ok, that's not the first company that suffers from NIH syndrome, or guys are simply too lazy or overloaded to look around for other stuff. The interesting point is: how the XML-based processing works in practice? The short answer is: very poor. And the weakest link in the whole chain is XSLT.
XSLT bloat
I won't dare to say that XSLT is worthless - perhaps in some contexts it can be useful, especially for transforming one document tree into another (valid) document tree, i.e. from DOM to DOM. XSLT gives you guarantee that input and output documents will be valid XML - this is crucial e.g. in SOA applications, transforming one document into other documents, to be processed by machines. (X)HTML is a document tree too, at least formally, but from the point of view of web browser to have perfectly valid XHTML is good, but not crucial, and from the point of view of web designer or developer the DOM behind it doesn't matter at all, and making the template valid XML is of no importance. For dynamic generation of HTML pages in most cases it is much easier if you treat the HTML code as a unformatted text, and make a web page template by embedding some special processing directives in such text. This approach was applied by JSP (first with scriptlets, and than with JSTL), Velocity, FreeMarker, and other technologies. Neither of those technologies use the strict XML as template. On the opposite side we have JSPX (JSP using strict XML) - it never caught on and I guess many Java developers have never met it; and XSLT.
I've used a lot of JSPs with JSTL. It wasn't perfect, but it worked. Now I have to do the same with XSLT and it's a nightmare. Things that took me half an hour to do with JSP take several hours in XSLT. This is a list of things I hate the most in XSLT:
1. Conditional arguments. For example: how to hide the row in table (using different CSS style), based on some CONDITION, with XSLT? See:
<tr>
<xsl:attribute name="style">
<xsl:choose>
<xsl:when test="CONDITION">
<xsl:value-of select="'visibility: visible'">
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'visibility: collapse'">
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
...
</tr>
and now the same with JSP 1.x:
<tr style='visibility:<%=CONDITION ? "collapse" : "visible"%>'>
...
</tr>
or with JSP 2.x:
<tr style='visibility:${CONDITION ? "collapse" : "visible"}'>
...
</tr>
2. Nested loops. In JSTL the <for-each> tag has the var attribute, which is variable that gets assigned the current element from the collection during looping. In nested loops, you choose different var names, and you have easy access to variable at any level. In similar <for-each> in XSLT there is not var attribute. You must use additional variables as child nodes, or some other workarounds. Its very easy to get lost.
3. Every XML-like fragment which is not an actual XML must be escaped. Say you have inlined javascript function which appends row to the table:
onclick="append('<tr><td></td><td></td></tr>')"
This will work in JSP quite good, but will blow up in XSLT with "could not compile stylesheet" message. You must escape each < character:
onclick="append('<tr><td></td><td></td></tr>')"
Nobody could understand what is going on here at first look now.
4. The functional approach applied in XSLT design, instead of the well known (for all programmers) procedural one, makes "thinking in XSLT" very hard. "Normal" approach (JSP, Velocity, etc) takes the HTML template starting from familiar <html><head>...<body>... and looks for special markers, where it puts data from "model". This data can be Java object or XPath-extracted data from other XML. XSLT does it in completely reverse way: it starts with <template match="..."><apply-templates>... so it takes the XML data document first, and tries to manipulate its content to obtain other document. As I said, in SOA processing this is fine. But in HTML generation it looks completely alien. I must say I always had problems with mental visualization of this process.
5. No formal XML schema for XSLT 1.0 exists. At least I couldn't find it - there is only unofficial DTD somewhere. This ruins IDE code completion abilities. And the XSLT is so complicated, that you can't simply learn it in one day (or even week), so some inline-help would be of real help.
Now take all those points together and multiply be all the places on the web page where dynamic content generation happens. Lengthy, complicated, with all those escapings, plus complicated XPath expressions, plus this "other-way-round" functional approach. That is developer horror. And worse, it is maintainer hell. In the current project, after two weeks I'm not able to understand the sections I have written a few days ago. I cannot imagine looking at it after several months. What's worse, the template code is so different than resultant HTML code, that navigation in the template and finding the actual place I need to edit takes always too much time.
After two weeks I'm fed up with XSLT. It's absolutely unproductive in web frameworks. Now I know why none of XML-based frameworks got big popularity ever. And I know I was completely wrong 3 years ago when I could bet that in the short time JSPX would replace JSP. Fortunately, it didn't.
Any alternatives?
Now that we know XSLT is evil, which view technology should we use in our projects? Stick with JSP? For JSF-based project I wouldn't use JSP for sure, because it simply doesn't play well with JSF, and instead I would go for something like facelets. But actually I wouldn't go for JSF either any longer (that's another story about the thing I used to believe in and predict long life to it, and that I was finally disappointed completely with). So for non-JSF projects there are JSP/JSTL, Velocity, FreeMarker, GSP for Grails projects, SiteMesh for page layouts, perhaps other technologies that I'm not aware of. JSP/JSTL is the most widely used, best known, and has best tool support, even if it is probably the worst one from the group. Take those crazy SQL-based tags in JSTL, or funny standard tags from JSP to deal with request parameters. Whey didn't they just took those tags from JSTL that are used always (if, for-each, format, ...) and make them part of standard JSP? Why I always have to include it as separate library on Tomcat? Besides, I said earlier that the actual input template doesn't have to be valid XML, but I must say I don't like constructs like <input value="<c:out ...>">. Tag inside other tag's attribute - this looks horrible. That is why now I think that template directives should not be constructed with XML tags: so all those custom tags, JSTL tags etc is the wrong direction. Such code is simply too hard to read, because it resembles too much HTML (ok, templates not always are used to generate HTML, but I guess in about 95% of cases they are). The better approach is to use some special characters, like # directives in Velocity, or [# in FreeMarker, or EL syntax ${...} in JSP/JSTL (but EL is too much limited and it is actually not directive; besides assumption that only getters can be called from EL was serious mistake: e.g. you cannot check collection size, because there is no getSize() method, only size()). Compare the if-then-else block created with JSP/JSTL:
<c:choose>
<c:when test="${expr1}">
...
</c:when>
<c:when test="${expr2}">
...
</c:when>
<c:otherwise>
...
</c:otherwise>
</c:choose>
with the same written with Velocity:
#if (expr1)
...
#elseif (expr1)
...
#else
...
#end
Which one is easier to read?
FreeMarker can be also good replacement for existing projects that already use XSLT. From what I see, you can bind the XML data document to some variable, and then access it with XPath queries from FreeMarker template to extract data. Velocity offers similar thing, it's called DVSL, but I doesn't look good to me, because it applies the same functional, other-way-round-alien-looking "apply-templates" approach as XSLT.
Velocity or FreeMarker integrates also well with Spring. Form my point of view, the only serious drawback of those technologies when compared to JSP, is IDE support. In the company where I do my painful job with XSLT, "the only IDE" is NetBeans (I think it is not obligatory, but simply all guys use it and all projects are not build with external Ant script or Maven, but simply by NetBeans, so it is hard to use other IDE anyway). I tried to find some plugin with Velocity or FreeMarker support for Netbeans (at least for syntax highlighting), but looks like there is no one. That's really strange for me - those technologies are on the market for many years, and are quite popular I think. So why there is no support in second most popular Java IDE for them? For Eclipse the situation is better, from what I see.
So if you start new project, think twice (or ten times) before jumping into XSLT. And if you use Eclipse, you can even think twice before using JSP/JSTL. Velocity or FreeMarker might be a better option.
Opinions expressed by DZone contributors are their own.
Comments