You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by "G. Todd Miller - XML Tech Ctr - Development" <Gl...@Sun.COM> on 2002/05/09 20:11:57 UTC

setSystemId() and TemplatesHandlers - Xalan Conf Tests (trax.sax)

If anyone is Xalan-land can help with this it would be great. The XSLTC
trax implementation is having difficulty passing a bunch of xalan conf tests
when the flavor is trax.sax (uses SAXSources rather than streams). The 
problem arises when there is an included stylesheet such as :

  <xsl:include href="periodgroup.xsl"/>
  
We throw a java.io.FileNotFoundException because at that point in the
compilation of an xsl stylesheet (read in as a SAXSource) we don't know
the system Id of the stylesheet and the only thing we can do is to look
for the included stylesheet (relative path) in the current directory.


java.io.FileNotFoundException: Could not load file periodgroup.xsl
at org.apache.xalan.xsltc.compiler.Include.parseContents(Include.java:127)
at org.apache.xalan.xsltc.compiler.Stylesheet.parseOwnChildren(Stylesheet.java:
   404)
at org.apache.xalan.xsltc.compiler.Stylesheet.parseContents(Stylesheet.java:
   376)
at org.apache.xalan.xsltc.compiler.Parser.createAST(Parser.java:380)
at org.apache.xalan.xsltc.trax.TemplatesHandlerImpl.getTemplates(
   TemplatesHandlerImpl.java:152)
at org.apache.qetest.xslwrapper.TraxSAXWrapper.transform(TraxSAXWrapper.java:
   252)
...


The Xalan conf test harness code that is mentioned at the bottom of the stack
trace looks like this:


   229 public long[] transform(String xmlName,String xslName, String resultName)
   230          throws Exception
   231  {
   232     preventFootShooting();
   233     long startTime = 0;
   234     long xslBuild = 0;
   235     long transform = 0;
   236     long resultWrite = 0;
   237
   238     // Create a ContentHandler to handle parsing of the xsl
   239     TemplatesHandler templatesHandler = saxFactory.newTemplatesHandler();
   240
   241     // Create an XMLReader and set its ContentHandler.
   242     // Be sure to use the JAXP methods only!
   243     XMLReader xslReader = getJAXPXMLReader();
   244     xslReader.setContentHandler(templatesHandler);
   245
   246     // Timed: read/build Templates from StreamSource
   247     startTime = System.currentTimeMillis();
   248     xslReader.parse(QetestUtils.filenameToURL(xslName));
   249     xslBuild = System.currentTimeMillis() - startTime;
   250
   251     // Get the Templates object from the ContentHandler.
 >>252     Templates templates = templatesHandler.getTemplates();
   253

In the test code, a TemplatesHandler (line 239) is used as a ContentHandler
for an XMLReader. As such, the XMLReader (xslReader,244) will parse a
stylesheet (line 248) into SAX Events. The TemplatesHandler from line 239
will receive those SAX Events and process them into a Templates (translet)
object that will be used to transform an input XML document further down
stream.  The test code gets the newly created Templates object on line
252. This Templates object has been created from the parsed stylesheet.

On line 252, a call to getTemplates() is made before any system Id is
set. According to the javadoc for the interface 'TemplatesHandler'
(javax.xml.transform.sax package), the 'setSystemId(String)' method
must be called on the TemplatesHandler *before* the startDocument event
is received by the TemplatesHandler. This is clearly not the case in
the test code.

In fact, if I introduce a new line (>>>) that set the system id as in this code:

   238   // Create a ContentHandler to handle parsing of the xsl
   239   TemplatesHandler templatesHandler = saxFactory.newTemplatesHandler();
 >>>     templatesHandler.setSystemId(QetestUtils.filenameToURL(xslName));
   240
   241   // Create an XMLReader and set its ContentHandler.

then XSLTC passes the tests (actually there are 59 more passes!)

Somehow Xalan does pass the test even without the setSystemId line proposed
above. I do not know how this is accomplished at this point.

I do not see how we can figure out the systemId ourselves in this test code
example. Again, looking at the test code above, the first time the
systemId is made known to the program is on line 248, when the XMLReader
is asked to parse the stylesheet. This information is known to the XMLReader,
however the XMLReader is not our code, and it does not forward this information
to the contained ContentHandler, which in this case is our XSLTC
TemplatesHandler. The TemplatesHandler only job is to sit there and absorb
SAX events. But there is no information in the SAX events on 'where' they
came from (i.e. the systemId of the Source). One scenario would be for
the TemplatesHandler, upon receipt of the 'startDocument' SAX event,
to ask the XMLReader for information about the Source it has parsed.
However, the TemplatesHandler is contained by the XMLReader and has no
outward reference to its container. Only the XMLReader has a reference
into the contained TemplatesHandler- not the other way around.

Any ideas?  Should Xalan conf test insert the 'setSystemId' call as proposed?
Why can Xalan handle this without the setSystemId call?

-Todd


=======================================================================
G. Todd Miller                        Sun Microsystems Computer Company
Software Systems Engineer             2 Network Drive, MS UBUR02-201
GE&IS XML Tech Center                 Burlington, MA 01803-0903
                                      781 442-0176
                                      781 442-1437 (fax)
                                      todd.miller@east.sun.com