1 Reply Latest reply on Apr 9, 2013 2:15 AM by Geoffroy Schneck

    XSLT Transformations cannot be performed on CQ

    Paolo Tognola

      Is it possible to programmatically run XSLT transformations in CQ from withing a sling JSP component?

       

      When i try, i get stuck while trying to get  a javax.xml.transform.Transformer instance from my xsl

      The xsl seems to get compiled correctly "Translet class loaded..." but not correctly available "... but unable to create translet instance."

       

      This is happening on versions: CQ 5.4, CQ 5.5, CQ 5.6 also on standard local crx-quickstart versions

       

      Can be reproduced like this:

      • Setup a sling component (simple jsp) for rendering an XSLT transformation
      • import a (previously tested) xslt stylesheet
      • get the jcr document view XML of the requested resource (resp. corresponding jcr subgraph)
        like: ses.exportDocumentView(path, xmlbos, false, false);
      • get the xsl stylesheet
        like: component.getLocalResource("out/dv.xsl/jcr:content").adaptTo(Node.class).getProperty("jcr :data").getBinary();
      • get a javax.xml.transform.TransformerFactory
        like: TransformerFactory xffac = TransformerFactory.newInstance();
      • try to get a javax.xml.transform.Transformer providing the previous stylesheet
        like: Transformer xfer = xffac.newTransformer([ABOVE_BINARY].getStream());
      • > this wan't work! and throw the following error: "Translet class loaded, but unable to create translet instance."

       

      Although i was able to verify correct reading of the XML and the XSL data as well as correct compilation of the XSL...

       

      Am i missing something? Is there some special cq built-in behaviour that should be used instead? Or some configuration on the TransformerFactory that has to be applied?

       

      Many thanks for any help on this!

      Regards

      Paolo Tognola

        • 1. Re: XSLT Transformations cannot be performed on CQ
          Geoffroy Schneck Level 2

          Hi Paolo,

           

          I could see this question was also raised in a Daycare ticket, I'm pasting the reply you got here also, so the entire community can benefit from it .

          So the problem seems to be a classloading issue, using the class loader from the TransformerFactory enables successful XSL transformation , as shown in the code below :

          ...
          //$$$
          final ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();

          try {

              //$$$
              Thread.currentThread().setContextClassLoader(javax.xml.transform.TransformerFactory.class.getClassLoader());

              // get xml
              ByteArrayOutputStream xmlbos = new ByteArrayOutputStream();
              ses.exportDocumentView(path, xmlbos, false, false);
              StreamSource xmlsrc = new StreamSource(new ByteArrayInputStream(xmlbos.toByteArray()));
               
              // get xsl
              Node xsln = component.getLocalResource("out/dv.xsl/jcr:content").adaptTo(Node.class);
              StreamSource xslsrc = new StreamSource(xsln.getProperty("jcr:data").getBinary().getStream());
             
              // run the transformation
              TransformerFactory xffac = TransformerFactory.newInstance();
              Templates tmpl = xffac.newTemplates(xslsrc);
              Transformer xfer = tmpl.newTransformer();
              xfer.transform(xmlsrc, new StreamResult(response.getOutputStream()));
          }
          catch(Exception x) {
              msg = "exception: " + x.getMessage();
              log.error(msg);
          }
          catch(Throwable t) {
              msg = "throwable: " + t.getMessage();
              log.error(msg);
          }
          finally {
              if(msg == null) msg = "finally";
              log.error(msg);

              //$$$
              Thread.currentThread().setContextClassLoader(oldLoader);
          }