[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

document() as extension mechanism

Subject: document() as extension mechanism
From: Joerg Pietschmann <joerg.pietschmann@xxxxxx>
Date: Fri, 20 Jul 2001 17:46:46 +0200
saxnotrecognizedexception namespaces
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 [expletive deleted] 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


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.