Re: [xsl] XSLT parameters in TrAX filter chains?

Subject: Re: [xsl] XSLT parameters in TrAX filter chains?
From: Paul Tremblay <phthenry@xxxxxxxxxxxxx>
Date: Thu, 11 Mar 2004 16:19:45 -0500
On Thu, Mar 11, 2004 at 10:52:01AM -0000, Stephen Summerfield wrote:
> 
> I am using the Java/TrAX XMLFilter to create a chain of XSLT transformations, I am wanting to be able to
> inject parameters into the XSLT stylesheets from the application. The Transformer interface allows this using
> setParameter(name, value). This works fine for simple XSLT transformations, but I can't get it to work for
> filter chains.
> 

I struggled with the same exact problem. It turns out that you *can't*
pass parameters to TRAX when you use XMLFiler. Michael Kay pointed out
that you don't really need t use XMLFilter at all. You can chain together
stylesheets directly in a SAX chain.

He points out that by not using XMLFilter, your code is simpler.

Here is my example code below. 

The code is rather long, but that's because most of it deals with
handling exceptions.

The important part for your code starts with the comment:

//LOOK HERE

Notice how I set up an instance of a TransformerHander for each
stylesheet. Then notice how I set the result of the first instance to
the next instance. The result of the last instance gets set to standard
otuput. You can also set this to SAX transformation. 

(However, I can't for the life of me figure out how to set up a chain
with a SAX transformation at the beginning of the chain using the type
of chain I set up below. If anyone has any example code, please show me! 
But that's another matter.)

I'm not a java programmer, so I can't tell you any more about the
intricacies of java, but I think this code should work. I think it might
be nice to have as a faq. It could serve as template for when you need
to chain stylesheets together. I know how to chain together
transformations using python and temporary files, but I think java is
superior for such a task.

Paul

*******************************************************


//standard java classes
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.FileNotFoundException;

//javax classes
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.TransformerConfigurationException;

//sax classes
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class ChainStyleSheets
{
  /**
   * Method main
   */
    public static void main(String argv[])
        throws  TransformerException, 
                TransformerConfigurationException, 
                IOException, 
                SAXException,
                ParserConfigurationException, 
                FileNotFoundException
    {
        try {
            chainStylesheets("xml/foo.xml", 
                            "xsl/foo.xsl",
                            "xsl/foo2.xsl",
                            "xsl/foo3.xsl"
                            );
        } catch( Exception ex ) { 
            handleException(ex);
        } 
    }

    public static void chainStylesheets(String sourceID, 
                                        String xsl_ID1,
                                        String xsl_ID2,
                                        String xsl_ID3
                                        )

        throws 
            TransformerException, 
            IOException, 
            SAXException,
            ParserConfigurationException 
    {


        TransformerFactory tfactory = TransformerFactory.newInstance();

        // Does this factory support SAX features?
        if (tfactory.getFeature(SAXSource.FEATURE))
        {
            // If so, we can safely cast.
            SAXTransformerFactory stfactory = 
                ((SAXTransformerFactory) tfactory);
      
            // A TransformerHandler is a ContentHandler that will listen for
            // SAX events, and transform them to the result.
            // Set up a hanlder for each style sheet. 

	    //LOOK HERE

            TransformerHandler handler1 = 
                stfactory.newTransformerHandler(new StreamSource(xsl_ID1));
            TransformerHandler handler2 = 
                stfactory.newTransformerHandler(new StreamSource(xsl_ID2));
            TransformerHandler handler3 = 
                stfactory.newTransformerHandler(new StreamSource(xsl_ID3));

            // Set up the parmeters. This paremeter will be passed to
            // stylesheet 1 (foo.xsl)
            handler1.getTransformer().setParameter("a-param", "a parameter set by java");
	    //parameters for stylesheet 2
            handler2.getTransformer().setParameter("b-param", "b parameter set by java");
      
            // Set the output of the stylesheets. The first stylesheet will
            // output to handle2, thus piping the result so the second
            // stylesheet can parse it. The second stylesheet outputs to the
            // terminal
            Result result1 = new SAXResult(handler2);
            Result result2 = new SAXResult(handler3);
            Result result3 = new StreamResult(new OutputStreamWriter(System.out));
            handler1.setResult(result1);
            handler2.setResult(result2);
            handler3.setResult(result3);

	    //END LOOK HERE
      
            // Create a reader, and set it's content handler to be the
            // TransformerHandler.
            XMLReader reader=null;

            // Create the SAX members
            // Use JAXP1.1 ( if possible )
        

            try {
              javax.xml.parsers.SAXParserFactory factory=
                  javax.xml.parsers.SAXParserFactory.newInstance();
              factory.setNamespaceAware( true );
              javax.xml.parsers.SAXParser jaxpParser=
                  factory.newSAXParser();
              reader=jaxpParser.getXMLReader();
              
            } catch( javax.xml.parsers.ParserConfigurationException ex ) {
              throw new org.xml.sax.SAXException( ex );
            } catch( javax.xml.parsers.FactoryConfigurationError ex1 ) {
              throw new org.xml.sax.SAXException( ex1.toString() );
            } catch( NoSuchMethodError ex2 ) {
            }
            if( reader==null ) reader = XMLReaderFactory.createXMLReader();
            reader.setContentHandler(handler1);

            // Parse the source XML, and send the parse events to the
            // TransformerHandler.
            reader.parse(sourceID);
        }
        else
        {
            System.out.println(
                "Can't do exampleContentHandlerToContentHandler because tfactory is not a SAXTransformerFactory");
        }
    }
  



    private static void  handleException( Exception ex ) {
        System.out.println("EXCEPTION: " );
        ex.printStackTrace();
        
        if( ex instanceof TransformerConfigurationException ) {
              System.out.println();
              System.out.println("Internal exception: " );
              Throwable ex1=((TransformerConfigurationException)ex).getException();
              ex1.printStackTrace();

              if( ex1 instanceof SAXException ) {
                  Exception ex2=((SAXException)ex1).getException();
                  System.out.println("Internal sub-exception: " );
                  ex2.printStackTrace();
              }
        }
    }
}

-- 

************************
*Paul Tremblay         *
*phthenry@xxxxxxxxxxxxx*
************************

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread