July 28, 2004

Tell me who are you and what are you processing

This is small trick for newbies looking for a way to get URI of a source XML and the stylesheet from within XSLT stylesheet. ...

Unfortunately neither XPath 1.0 nor XSLT1.0 don't provide any solutions for the problem. Usual answer is "pass it as a parameter". That's a good one, but not always suitable (e.g. when transforming client side with <?xml-stylesheet?> PI). Next answer is "use Saxon's saxon:system-id() extension function or write your own". Latter is what I'm going to illustrate.

Simple, ain't it:

<xsl:stylesheet version="1.0" 

  <msxsl:script language="javascript" 
    function uri(nodelist) {
      return nodelist[0].url;
  <xsl:template match="/">
    <p>Currently processing XML document URI is 
      <tt><xsl:value-of select="ext:uri(/)"/></tt></p>
    <p>Currently processing XSLT stylesheet URI is 
      <tt><xsl:value-of select="ext:uri(document(''))"/></tt></p>
The result (try http://www.tkachenko.com/samples/detect-uri.xml) is:
Currently processing XML document URI is http://www.tkachenko.com/samples/detect-uri.xml

Currently processing XSLT stylesheet URI is http://www.tkachenko.com/samples/detect-uri.xsl

PS. Of course extension functions are not portable and above works only in IE/MSXML3+.

PPS. Of course it only works well when XML documents are loaded from a URI, not generated on the fly.

PPPS. XPath 2.0 will fix the problem providing fn:document-uri and fn:base-uri() functions.