The Blog

Jun 10, 2008

Performing XSL Transformations with JavaScript 

by Maxim Porges @ 11:38 PM | Link | Feedback (3)

At Highwinds, we document release notes for our software releases on our wiki. While this is a necessary and sensible practice, I do find it a little tedious since it requires copying some of the information from Bugzilla to our wiki.

Since I am lazy, and Bugzilla allows export of search results to XML, I made an XSL style sheet to convert the results of a bug search for a particular release to wiki text that TWiki would understand. This was all well and good, but required me to go through a number of manual steps:

1) Run the search for bugs in a particular release in Bugzilla
2) Push the button to pull the results as XML
3) Save the XML
4) Open the XML in a text editor and add the line to reference the XSL style sheet
5) Save the XML file and open it in a browser
6) Copy the XML-transformed-to-wiki-text to the clipboard
7) Open the release notes page on the wiki
8) Edit the release notes page, pasting the wiki text and saving the article

While this process was better than manually writing the wiki text (especially since I have the transformer create links from the release notes to the Bugzilla articles, lay the bugs and features out separately, and put the entire thing in a table-based layout), it still sucked that I had to go through it all. So, I decided that since I've been meaning to learn Ajax forever, I would use this opportunity to figure out how to write some JavaScript that would post the search parameters to Bugzilla (taking care of items #1 - #3) and apply the stylesheet (knocking out #4 - #6). If I can embed the JavaScript in the wiki article, then #7 and #8 would also be automated, leaving me even more free time than usual to stare at my desk while eating Girl Scout cookies.

So, I did a little research, and found an XML processing library for JavaScript called Sarissa. In combination with Scriptaculous/Prototype (which was dead easy to get started with), I had the script I wanted written and working in under an hour.

Initially, I embedded the XML for the data and style sheet, with the intention of making this dynamic via Ajax calls after it was all working. I thought that others might be interested in the source, so here it is. The XML for data/style sheet are obviously simplified since I had to smash them all together on one line.


<html>
<head>
<script src="javascripts/prototype.js" type="text/javascript"></script>
<script src="javascripts/scriptaculous.js" type="text/javascript"></script>
<script src="../sarissa-full-0.9.9.4/gr/abiss/js/sarissa/sarissa.js" type="text/javascript" charset="utf-8"></script>

<script>

function performXsltTransformation(xml)
{
var xsltDoc = '<?xml version="1.0" encoding="ISO-8859-1"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/cds/cd"><p><b><xsl:value-of select="artist"/>:</b><xsl:value-of select="title"/></p></xsl:template></xsl:stylesheet>';
var xsltDocument = (new DOMParser()).parseFromString(xsltDoc, "text/xml");

var xsltProc = new XSLTProcessor();
xsltProc.importStylesheet(xsltDocument);

var htmlDoc = xsltProc.transformToDocument(xml);
var htmlString = new XMLSerializer().serializeToString(htmlDoc);
$("display").innerHTML = htmlString;
}

window.onload = function()
{
var xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><cds><cd><title>Super Duper CD</title><artist>Michael Jackson</artist></cd></cds>';
var domDocument = (new DOMParser()).parseFromString(xml, "text/xml");

performXsltTransformation(domDocument);
}

</script>
</head>

<body>
<div id="display"></div>
</body>

</html>


This worked like a treat, and I was all pleased with myself. Unfortunately, as I got in to the Ajax piece, I found out that you can't have a page served from one domain (such as our wiki) pull content from a server on another domain (such as our Bugzilla server) due to XSS security sandboxing. It appears that there are a few hacks to get this to work, but nothing that really makes my life easier for my specific use case.

In any event, I got all the JavaScript libraries for doing Ajaxy things together and dipped my toe in, so it wasn't a total loss. If anybody has any neat suggestions for getting around the two-different-servers thing I'd like to hear them.