This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
document() as extension mechanism
- To: XSL List <xsl-list at lists dot mulberrytech dot com>
- Subject: [xsl] document() as extension mechanism
- From: Joerg Pietschmann <joerg dot pietschmann at zkb dot ch>
- Date: Fri, 20 Jul 2001 17:46:46 +0200
- Organization: ZKB
- Reply-To: xsl-list at lists dot mulberrytech dot com
Hello,
i recently got some ideas for innovative uses of document() in
conjunction with custom-written URIResolver's and XSL input sources.
(Java only examples, sorry).
Relevant questions are at the end of this post.
1. Read the current date/time.
Refine the following hack to carefully designed and crafted code and
insert it into your URIResolver's resolve method.
if( href.startsWith("time:") ) {
SAXSource source = new SAXSource();
source.setInputSource(new InputSource(
new StringReader("<time>"+new Date().toString()+"</time>")));
return source;
}
Read the current date/time with
<xsl:value-of select="document('time:foo')/time"/>
The URL could be used to specify a locale, or a host to read from,
or whatever you like (ideas welcome!).
2. Get a directory listing.
You can read the listing into a string and feed it into the processor
via a StringReader as in the example above, but it might be more
interesting to demonstrate how to do this using a customized input
source and XML reader.
Drop this into your URIResolver:
if( href.startsWith("filelist:") ) {
return new SAXSource(new FileListXMLReader(),
new FileListInputSource(
new File(href.substring("filelist:".length()))));
}
You'll need an apropriate InputSource (terseness favoured over
robustness):
import java.io.*;
import java.util.*;
import org.xml.sax.*;
public class FileListInputSource extends InputSource {
private File dir;
public FileListInputSource(File d) { dir=d; }
public String[] list() { return dir.list(); }
}
The Reader class is somewhat more elaborated. Getting strings through
the SAX API sucks mightily (is there a better way than shown below?).
The only really interesting routine is parse(InputSource) buried
somewhere in the middle of the following code:
import java.io.*;
import java.util.*;
import org.xml.sax.*;
public class FileListXMLReader implements XMLReader {
private int len=128; private char buf[]=new char[len];
private synchronized void writeContent
(ContentHandler contentHandler,String s) throws SAXException {
if( s.length()>len ) { do {len=2*len;} while( s.length()>len );
buf=new char[len]; }
s.getChars(0,s.length(),buf,0);
contentHandler.characters(buf,0,s.length());
}
// XML Reader
private ContentHandler contentHandler;
private DTDHandler dtdHandler;
private EntityResolver entityResolver;
private ErrorHandler errorHandler;
public ContentHandler getContentHandler() { return contentHandler; }
public DTDHandler getDTDHandler() { return dtdHandler; }
public EntityResolver getEntityResolver() { return entityResolver; }
public ErrorHandler getErrorHandler() { return errorHandler; }
public boolean getFeature(java.lang.String name)
throws SAXNotRecognizedException, SAXNotSupportedException
{
if( name.equals("http://xml.org/sax/features/namespaces")
|| name.equals("http://xml.org/sax/features/namespace-prefixes") ) {
return true;
} else {
throw new SAXNotRecognizedException("not implemented: "+name);
}
}
public java.lang.Object getProperty(java.lang.String name)
throws SAXNotRecognizedException, SAXNotSupportedException
{ throw new SAXNotRecognizedException("not implemented: "+name); }
public void parse(InputSource input)
throws java.io.IOException, SAXException {
if( contentHandler==null ) {
throw new SAXException("No content handler");
}
try {
FileListInputSource source=(FileListInputSource)input;
Attributes attrs=new org.xml.sax.helpers.AttributesImpl();
contentHandler.startDocument();
contentHandler.startElement("","files","files",attrs);
String list[]=source.list();
if( list!=null ) {
for( int i=0;i<list.length;i++ ) {
contentHandler.startElement("","file","file",attrs);
writeContent(contentHandler,list[i]);
contentHandler.endElement("","file","file");
}
}
contentHandler.endElement("","files","files");
contentHandler.endDocument();
}
catch( ClassCastException e ) {
throw new SAXException("Need filelist input source");
}
}
public void parse(java.lang.String systemId)
throws java.io.IOException, SAXException {
// leave this to your imagination, should use new File(systemId).list()
return;
}
public void setContentHandler(ContentHandler handler) { contentHandler=handler; }
public void setDTDHandler(DTDHandler handler) { dtdHandler=handler; }
public void setEntityResolver(EntityResolver resolver) { entityResolver=resolver; }
public void setErrorHandler(ErrorHandler handler) { errorHandler=handler; }
public void setFeature(java.lang.String name, boolean value)
throws SAXNotRecognizedException, SAXNotSupportedException
{
if( name.equals("http://xml.org/sax/features/namespaces")
|| name.equals("http://xml.org/sax/features/namespace-prefixes") ) {
} else {
throw new SAXNotRecognizedException("not implemented: "+name);
}
}
public void setProperty(java.lang.String name, java.lang.Object value)
throws SAXNotRecognizedException, SAXNotSupportedException
{ throw new SAXNotRecognizedException("not implemented"); }
}
The following snippet will insert a listing of the current directory
of the process into an html-page:
<xsl:for-each select="document('filelist:.')/files/*">
<p><xsl:value-of select="."/></p>
</xsl:for-each>
You can easily extend the XMLReader to provide file lengths,
modification dates, diverse attributes and whatnot to the XSL
processor (use listFiles() instead of list()). If you use TrAX/JAXP
you can also use the FileListXMLReader for as your main document
input source (yes, this can be useful too: directory listing pages,
styled as you like...).
3. Another idea: read parameters of a servlet with document('parameters:').
Unfortunately, the code ist too long to be quoted here :-)
Saxon allows to specify the URI resolver on the command line, therefore
you don't need to deal with the source of of the processor just for
experimenting.
java -classpath ".;saxon.jar" com.icl.saxon.StyleSheet \
-r MyURIResolver foo.xml foo.xsl
If you use TrAX/JAXP, invoke setURIResolver on your transformer.
Questions:
1. I think this should provide a rather portable way to allow access
to various system ressources at lease for Java-based processors.
What's your opinion?
2. Other ideas?
3. Anybody out there wanting to host a repository for resolvers/sources? :-)
4. Could this be of interest to the standards people?
Regards
J.Pietschmann
--
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list