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

URIResolver howto

Subject: URIResolver howto
From: "Robert Koberg" <rob@xxxxxxxxxx>
Date: Tue, 1 Oct 2002 07:43:44 -0700
xsl include uriresolver
Hi, [I sent this with the wrong email address, sorry if it comes through twice]

I recieved a few requests for a better example of how to use the URIResolver. I
hope the information below helps.

When you need control over xsl:include/import or the document(), you need to use
an URIResolver - you cannot do it in your stylesheet. This is very useful when
you have a 'primary' XSL[1]  and it includes, imports or uses document() to
bring in other XML/XSL files/streams from two or more different points of
control.

As a simple example lets say a user logs on to a server-side application. The
user can choose different navigation styles to get around a site (dynamic JS or
static HTML). You would need to somehow get or keep a user preference that tells
the app which nav option they have choosen.

We might have a primary XSLT like:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="head.xsl"/>
<xsl:include href="banner.xsl"/>
<xsl:include href="nav.xsl"/>
<xsl:include href="footer.xsl"/>
<xsl:template match="/">
<html>
  <xsl:call-template name="head"/>
  <body>
    <xsl:call-template name="banner"/>
    <div id="leftcol">
      <xsl:call-template name="nav"/>
    </div>
    <div id="centercol">
       call some templates
    </div>
    <div id="rightcol">
      <div class="floater">
        call some templates
      </div>
    </div>
    <br clear="all"/>
    <xsl:call-template name="footer"/>
  </body>
</html>
</xsl:template>
</xsl:stylesheet>

There are two different sets of the head and nav and to keep things modular. So
you might use static_head.xsl & static_nav.xsl or dynamic_head.xsl &
dynamic_nav.xsl. You need an URIResolver to handle which set to include.

You may have a method that starts transformations in the app:

void xform(ServletContext servlet_context, HttpServletRequest req,
HttpServletResponse res, long _start_time)
  	throws TransformerException, java.io.IOException {

  System.setProperty(
    "javax.xml.transform.TransformerFactory",
    "com.icl.saxon.TransformerFactoryImpl");
  ServletOutputStream out = res.getOutputStream();
  HttpSession http_session = req.getSession();
  String nav_style = http_session.getAttribute("nav_style").toString();
  String source = http_session.getAttribute("source").toString();
  String style = http_session.getAttribute("style").toString();
  try {
      Templates pss = tryCache(servlet_context, style, nav_style);
      Transformer transformer = pss.newTransformer();
      Properties details = pss.getOutputProperties();
      String mime =
pss.getOutputProperties().getProperty(OutputKeys.MEDIA_TYPE);
      if (mime==null) {
        res.setContentType("text/html");
      } else {
        res.setContentType(mime);
      }
      transformer.setParameter("nav_style", nav_style);
      transformer.transform(
          new StreamSource(source)),
          new StreamResult(out));
      out.close();
      out.flush();
    } catch (Exception err) {
      System.out.println(err);
    }
}

Your tryCache method might look like:

private synchronized Templates tryCache(ServletContext serv_context, String
path, String nav_style)
    throws TransformerException, java.io.IOException {
  String full_path = serv_context.getRealPath(path);
  Templates x = (Templates)this.cache.get(path);
  if (x==null) {
      TransformerFactory factory = TransformerFactory.newInstance();
      factory.setURIResolver(new MyResolver(serv_context, nav_style));
      x = factory.newTemplates(new StreamSource(new File(full_path)));
      this.cache.put(path, x);
  }
  return x;
}

This primary XSLT needs to find files identified in the xsl:includes/imports and
document(). The following URIResolver simply checks the href argument
automatically sent in by the transformation process. The href argument is the
value of the href in the xsl:include/import or the first (or only) argument from
the document function. The base argument is either the location of the primary
XSLT or the second argument in the document(). If it sees head.xsl or nav.xsl it
prepends the filename with the nav style preference string:

class MyResolver implements URIResolver {
  String base_path;
  String nav_style;
  public MyResolver(ServletContext context, String style) {
    this.base_path = context.getRealPath("/WEB-INF/styling/");
    this.nav_style = style;
  }

  public Source resolve(String href,String base) {
    StringBuffer path = new StringBuffer(this.base_path);
    if (href.equals("head.xsl") |
         href.equals("nav.xsl")) {
      path.append(this.nav_style);
      path.append("_");
    }
    path.append(href);
    File file = new File(path.toString());
    if(file.exists()) return new StreamSource(file);
    return null;
  }
}


best,
Rob Koberg
livestoryboard.com

[1] the XSL used as the argument in the transformation against the main source
XML



 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.