Douglas,
I recently had to do something very similar, except I'm using translets
wrapped in a Templates.
The approach I took was to write a factory class that holds a static HashMap
of translet name:template instance pairs. Whenever I need a transformer - I
call my method in the factory to get transformers, it checks its hashmap to
see if it already has a templates instance for the requested translet, if it
does it'll return it, otherwise it'll create one add it to the hashmap and
then return it.
I'm using this in a J2EE application and everything appears to be working
fine
Keep in mind that a Transformer is a lightweight object that tracks state
information during the transformation and that for each transformation, a
new Transformer should be created. Because of this, I hold the Templates
instances in my static hashmap and not a Transformer.
I also have a class that build translets (Templates) that is an ANT task if
you need it.
Below is the code I wrote:
---------
/*
* xslTransletFactory.java
* Bryan K. Hunter
*/
// Import standard Java (JDK) packages
import java.util.HashMap;
import javax.xml.transform.stream.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
// Import 3rd party commercial packages
import org.xml.sax.*;
import org.apache.xalan.xsltc.dom.*;
/** **********************************************************************
* This class serves as a factory to return the proper instance of a
* Transformer given the translet String literal name.
* @author Bryan K. Hunter ([EMAIL PROTECTED])
* **********************************************************************/
public class xslTransletFactory
{
private static HashMap _transletsHM = new HashMap();
private static BuildxslTemplate _btt = null;
public synchronized static Transformer getTransformer(String
transletName)
throws TransformerException
{
Transformer transformer = null;
Templates templates = null;
if (_transletsHM == null) {
_transletsHM = new HashMap();
} // end if
if (_transletsHM.containsKey(transletName)) {
templates = (Templates)_transletsHM.get(transletName);
} else {
// create a new Transformer and add it to transletsHM
if (_btt == null) {
_btt = new BuildxslTemplate();
} // end if
templates = _btt.execute(transletName);
_transletsHM.put(transletName, templates);
} // end if-else
if (templates == null) {
throw new TransformerException("Unable to create and return the
requested Transformer for " +
transletName);
} // end if
transformer = templates.newTransformer();
return transformer;
} // end public static Transformer getTransformer(String)
} // end public class xslTransletFactory
-------
/*
* BuildxslTemplate.java
* Bryan K. Hunter
*/
// Import standard Java (JDK) packages
import java.io.*;
import javax.xml.transform.stream.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
// Import 3rd party commercial packages
import org.xml.sax.*;
import org.apache.xalan.xsltc.dom.*;
/** **********************************************************************
* Helper class to build Transformer instances
* @author Bryan K. Hunter ([EMAIL PROTECTED])
* **********************************************************************/
public class BuildxslTemplate
{
public BuildxslTemplate() {}
public Templates execute(String transletName)
throws TransformerException
{
Templates templates = null;
try {
templates = readTemplates(transletName);
} catch (Exception e) {
throw new TransformerException(e);
} // end try-catch
return templates;
} // end public Templates execute(String)
/**
* Reads a Templates object from a file
*/
private Templates readTemplates(String file) {
try {
/*
FileInputStream ostream = new FileInputStream(file);
ObjectInputStream p = new ObjectInputStream(ostream);
Templates templates = (Templates)p.readObject();
ostream.close();
return(templates);
*/
/* Failed because the ".translet" file is not a valid class
ClassLoader loader = this.getClass().getClassLoader();
Class clazz = loader.loadClass(getBaseName(file));
return (Templates)clazz.newInstance();
*/
// this code works!
ClassLoader loader = this.getClass().getClassLoader();
InputStream isTranslet = loader.getResourceAsStream(file);
ObjectInputStream p = new ObjectInputStream(isTranslet);
Templates templates = (Templates)p.readObject();
isTranslet.close();
return (templates);
} catch (Exception e) {
System.err.println(e);
e.printStackTrace();
System.err.println("Could not read file "+file);
return null;
} // end the-catch
}
/**
* Returns the base-name of a file/url
*/
private String getBaseName(String filename) {
int start = filename.lastIndexOf(File.separatorChar);
int stop = filename.lastIndexOf('.');
if (stop <= start) stop = filename.length() - 1;
return filename.substring(start+1, stop);
}
} // end public class BuildTransletTransformer
-------
Here is the method to do the actual transformation:
/**
* Return String of XSL Transformation
* @param sXML the XML String
* @param sXSL the XSL Translet file name
* @return String of XSL Transformation result
* @exception TransformerException
* @exception TransformerConfigurationException
* @exception FileNotFoundException
* @exception IOException
*/
public String processTranslet(String sXML, String sXSL)
throws TransformerException, TransformerConfigurationException,
FileNotFoundException, IOException
{
String resultString = null;
Transformer transformer = xslTransletFactory.getTransformer(sXSL);
StreamResult result = null;
if (transformer == null) {
throw new TransformerException("Unable to create new
Transformer");
} else {
StreamSource document = new StreamSource(new
StringReader(sXML));
result = new StreamResult(new StringWriter());
transformer.transform(document, result);
} //end if-else
if (result != null) {
resultString = ((StringWriter)result.getWriter()).toString();
} else {
resultString = null;
} // end if-else
return resultString;
} // end public String process(String, String)
------
This is how I call the processTranslet code (SimpleTransform is my class
where I've placed processTranslet and xmlString is my xml as a String:
SimpleTransform st = new SimpleTransform();
String resultsBody = st.processTranslet(xmlString, "mytranslet.translet");
------
Hope this helps.
Bryan Hunter (bryan.hunter 'at' omnichoice.com)
> -----Original Message-----
> From: Douglas Conklin [mailto:[EMAIL PROTECTED]
> Sent: Friday, January 25, 2002 3:03 PM
> To: [EMAIL PROTECTED]
> Subject: Getting a transformer from a translet.
>
>
> I am attempting to use the XSLTC API to apply compiled style
> sheets to XML.
>
> Some instances of my component will want to use a compiled
> stylesheet, and
> some a plain text style sheet. For this reason I would like to cache a
> Transformer in each instance for the transformation to employ
> as much code
> reuse as I can.
>
> I know I can get a Transformer from a Templates object, but I
> don't want to
> compile the style sheets at runtime.
>
> The command line compiler will only compile to Translets.
>
> Is there anyway to get a Transformer object given only a
> Translet, or are my
> two choices to serialize Templates for reading at runtime, or
> using two
> separate transformation methods depending on compiled or not?
>
> Thanks in advance.
>
> easy,
> douglas d
>
>
>
>
>
>