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