External questions

1. How to get style-sheet relative paths?
2. How to determine absolute path of processed xml
3. Get the current xml file name
4. Obtain source file name


How to get style-sheet relative paths?

Michael Kay

> I want to use this directory structure:

>   somepath/data/DataFiles.xml

> for xml files containing the data and

>   somepath/style/StyleFiles.xsl

> for the style info to be used.

> The explorer knows about the stylesheet to be used by finding a

>   <?xml-stylesheet type="xsl/text" href="../style/StyleFiles.xsl"?>

XSLT 2.0 would allow you to write


But of course that doesn't help very much because you need a solution that works in IE. Unfortunately I don't think it's possible: although the base URI of a stylesheet instruction is part of the context in 1.0, it's accessible only through the document() function.


How to determine absolute path of processed xml

Michael Kay

In XSLT 2.0 you can do document-uri(/).

It only work if the systemId is actually known, which may not be the case if for example the source was supplied as a DOMSource.

A more portable solution is to pass the URI to the stylesheet as a parameter.


Get the current xml file name

Colin Adams

I'm looking for a function that helps me to read and process
several .xml files by document(). the problem is that when i say


the document() function tries to read the xml file in the path of the
current xslt (!) file. and that's not working for me. so I want to
redirect the document() function to the path of the directory of the
current .xml file.


reports the whole (!) uri of the current xml file. that includes the
path I'm looking for, like


and that's fine. but how can I now cut off 'myfile.xml'

document (concat(document-uri(/),'/../','nextfile.xml')) 

should do the trick.

If you are using XSLT 2.0, you can use the resolve-uri function which will be a bit neater.

Owen Rees adds

If you can use document-uri then you should be able to use resolve-uri - both are new in XPath 2.0.


See also base-uri.


Obtain source file name

Andrew Welch et al

> is there a function in xslt that gives me the clean filename of the
> processed xml file? like
>    'myfile.xml'
>    'test.xml'
>    'anyfilename.xml'
> i do *not* need the document-uri. only the filename of the current
> processed xml file.

In xslt 2.0 I use:

tokenize(base-uri(.), '/')[last()]

Colin Adams adds

That's not sound - . might not be the document node - if it's an element with an xml:base attribute in scope, then you may get something very spurious indeed.

Using document-uri in your expression looks sounder.

Andrew responds with I think its safe to use on all nodes except namespace nodes: W3C

Regarding xml:base you should get whatever's defined in the xml:base shouldn't you? In which case it's what the XML author intended, and may be what you need to know at that point, depending on your requirements.

And Colin comes back (Ednote: I like these threads :-)

The OP's requirements were the filename, not the base-uri. if his requirements were indeed the XML author's view of the base-uri, then it would be perfect.

   >> If the OP is invoking a transformation from the command line,
   >> then he can pass in the file name as a parameter. That is
   >> reliable.

   Andrew> Indeed, but in the general case you'll be fine with
   Andrew> tokenize(base-uri(.),'/')[last()]

Well, no. (and not even with document-uri substituted for base-uri). What you get is the last path segment, plus possible query parameters and fragment identifier, from the base, or document, uri.

In general, this has no relation to a file name.

In the case of a file: uri, even then it is not sound. If you want the file name, and you get instead a fragment identifier tacked on a file name, you don't get what you want.

So a further tokenization is necessary to remove query parameters and fragment identifier.

If it's not a file uri, then all bets are off.

David Carlisle comes in with

I'd probably do replace(base-uri(/),'.*/','') to remove the path component rather than tokenize and last() but it probably doesn't make much difference really. You could add |[\?#].* to the regex to also remove query and fragment identifiers if they were a possibility.