Todd, I'm reading this too fast... it's been a crazy week. So forgive any
incorrect info. (Actually every week is crazy these days).
> 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));
Unless I'm misreading, this should be enough to tell Xalan what the base
URL (system ID) is. This is because the reader will call
ContentHandler#setDocumentLocator(Locator locator), which is enough to tell
org.apache.xalan.processor.StylesheetHandler where system ID location is
(and other things, like line numbers... very useful!!!). Note that the
Locator object is set once, and then is kept updated according to the
current line by the parser.
If your ContentHandler event provider doesn't call setDocumentLocator, only
then do you have to call
templatesHandler.setSystemId(QetestUtils.filenameToURL(xslName));. As a
matter of fact, setSystemId isn't really needed for the API given
setDocumentLocator... I guess it was just put there as a bit more
convenient than setDocumentLocator (it's been long enough that I don't
remember...).
Anyhow, hope this makes sense and is useful. (Or I may be in too great of
a rush and it might be garbage).
-scott
"G. Todd Miller -
XML Tech Ctr - To: [EMAIL PROTECTED]
Development" cc: [EMAIL PROTECTED],
(bcc: Scott Boag/Cambridge/IBM)
<Glenn.Miller@Sun Subject: setSystemId() and
TemplatesHandlers - Xalan Conf Tests (trax.sax)
.COM>
05/09/2002 02:11
PM
Please respond to
xalan-dev
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)
[EMAIL PROTECTED]