Wednesday, 3 June 2009

Prototype and running XSLT from JavaScript

I had some problem marrying the usual method of running an XSLT with prototype's library. Here's my project: Given an xml file of 'bad channel identifiers' for a module (where channels run 0-767), display the bad channels as bars on a graph in SVG in response to a user clicking on another web page link somewhere. I chose to generate the SVG using a parametrised XSLT, but I need to pass the parameters...so I'll be running the XSLT 'manually' from JavaScript instead of using the stylesheet association.
Step 1. : Perform a transform manually using a loaded stylesheet and xml. I'll load both via an Ajax request... (this is not production code, but might help someone... and note that I already loaded the prototype library)
var Transformer = Class.create({

initialize: function(){
  this.processor = new XSLTProcessor();
},

setXslt: function(xslPath){
  //need to bind, otherwise 'this' refers to the event context, not the class
  new Ajax.Request(xslPath, {asynchronous: false, onSuccess: this._setXsl.bind(this),
  onFailure: function(r){alert("failure to load xsl");}});
  
},
_setXsl: function(r){
  this.stylesheet=r.responseXML;
  if (this.stylesheet==''){
    alert("Empty stylesheet");
  }

  this.processor.importStylesheet(this.stylesheet);
},

setXml: function(docPath){
  //need to bind, otherwise 'this' refers to the event context, not the class
   new Ajax.Request(docPath, {asynchronous: false, onSuccess: this._setXml.bind(this),
  onFailure: function(r){alert("failure to load xml");}});
},

_setXml: function(r){
  this.xmlDoc = r.responseXML;
  if (this.xmlDoc==''){
    alert("Empty xml doc");
  }
 },

exec: function(){
  var fragment = this.processor.transformToFragment(this.xmlDoc, document);
  return fragment;
}

});

function transform() {
var transformer = new Transformer();
transformer.setXslt("xsl/test.xsl");
transformer.setXml("xml/hello.xml");
f = transformer.exec();
$('insert').appendChild(f);
}

No comments: