You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-users@xalan.apache.org by Thomas Nichols <nx...@yahoo.co.uk> on 2002/10/08 18:38:34 UTC

Implementing a TrAX pipeline with multiple inputs ("fan-in") - moderately long

Hi,

I'm struggling to develop an elegant API that will do the following - I'd 
be very grateful for any recommendations. The API needs to
     - accept two (or three, or four) javax.xml.transform.Source objects 
(to be fed into a proprietary engine)
     - generate a javax.xml.transform.Result
     - use exclusively JAXP 1.1 and SAX2 features - sadly, no Xalan extensions
     - allow a chain of user-specified transforms to be applied to each 
input and to the output.

I'd like the transforms to be definable as XSLT scripts, XSLTC translets 
(for those clients wishing to use Xalan/XSLTC) or as custom Java code. 
Transformers would seem to fit the bill for this.

I've read http://xml.apache.org/xalan-j/usagepatterns.html#outasin and 
worked with the Pipe, UseXMLFilters and trax sample apps. A workable 
approach seems to be

o   Use "pull-mode" on the inputs, allowing the user to specify a chain of 
XMLFilters built from XSL/whatever and using filter.setParent() to connect 
them together, the "bottom-most" filter being converted to a SAXSource (by 
the appropriate ctor) and passed into the engine. This is as per the 
"UseXMLFilters" example:


     XMLReader reader = saxParserFactory.newSAXParser().getXMLReader();
     XMLFilter xmlFilter1 = saxTransformerFactory.newXMLFilter(new 
StreamSource("in1.xsl"));
     XMLFilter xmlFilter2 = saxTransformerFactory.newXMLFilter(new 
StreamSource("in2.xsl"));
     xmlFilter1.setParent(reader);
     xmlFilter2.setParent(xmlFilter1);
     // xmlFilter2 can now be wrapped for passing into the engine as a Source:
     SAXSource sourceA= new SAXSource(xmlFilter2, userSpecifiedSource);

     The same can be done for the second (third, fourth) input to give 
sourceB (sourceC, sourceD).


o  Use "push-mode" on the output as per "Pipe":
     TransformerHandler handler1 = saxTransformerFactory.newTransformerHandler
         (new StreamSource("out1.xsl"));
     TransformerHandler handler2 = saxTransformerFactory.newTransformerHandler
         (new StreamSource("out2.xsl"));

     // I know Serializer is Xalan-specific, I use it for illustration only.
     Serializer serializer = ....;
     SAXResult serResult= new SAXResult(serializer.asContentHandler());
     handler1.setResult(handler2);
     handler2.setResult(serResult);
     SAXResult handler1AsResult = new SAXResult(handler1);

This entire assembly - Pulling inputs and Pushing output - can then be 
started with an
assembly.start (sourceA, sourceB, handler1AsResult);

.... BUT...
  this means using XMLFilters to define the "input" transforms, and 
TransformerHandlers to define the "output" transforms. I'm also unclear 
whether XSLTC translets can be represented as XMLFilters.

QUESTION:
For consistency and simplicity, I'd like to use one type for both input and 
output transforms - how can I achieve this?

The engine needs asynchronous access to the input documents - when munching 
through the inputs, it may take some from docA then some from docB, etc. 
This seems to mandate pull for the input. Is there any way of achieving the 
same result using TransformerHandlers instead of XMLFilters?

Other resources that have helped clarify things:
XPipe - http://xpipe.sourceforge.net/
GNU JAXP "gnu.xml.pipeline" - http://www.gnu.org/software/classpathx/jaxp/ 
and http://www.gnu.org/software/classpathx/jaxp/apidoc/index.html


Any suggestions would be very welcome - TrAX pipelines are a very powerful 
architecture, I'd like to build with the most flexible solution I can find.

Thanks for taking the time to read this,
Best Regards,
Thomas.