Dynamic path in document function() - xslt

The XML file name is specific but I need to build a dynamic path. I have tried using a variable to build the path but it didn't work:
<xsl:variable name="path">
...conditional code
</xsl:variable> <xsl:value-of select="document('myXML.xml')/worksheets/$path"/>
2.0 solutions ok.

Evaluation of any dynamically-generated XPath expression is not supported by the XSLT 1.0 or XSLT 2.0 standards. It will be supported in XSLT 2.1.
If the dynamically-generated XPath expression is not too complex, the technique in this answer can be used successfully:
Retrieving XML node from a path specified in an attribute value of another node

You need an extension function, XPath 2.0 does not support dynamic compilation/evaluation. Saxon has saxon:evaluate. Even if your processor does not support such function you might be able to implement it yourself as an extension function.

Related

How to run the <xsl:for-each-group select="*" group-adjacent="boolean(self::table)"></xsl:for-each-group> of xslt2.0 by using xalan

Actually I have two methods :
one is : document-location()
and other is :
<xsl:for-each-group select="*" group-adjacent="boolean(self::table)">
first method is supported to xalan but not saxon and second method is supported saxon but not xalan .
for this I have created two files for two methods . But I dont want to create two different files .Is there any method which works same as in xalan?
The <xsl:for-each-group> construct was introduced in XSLT 2.0, and Xalan only supports XSLT 1.0. If you need to do grouping in XSLT 1.0, you'll have to use the Muenchian grouping method. If there are things in your stylesheet that prevent you migrating from Xalan to Saxon to take advantage of XSLT 2.0 (and 3.0), then please tell us exactly what the issues are and we can probably help you with the migration. (That would be best done in a new question.)
I want ro run document-location() method using saxon.
I cannot find any documentation of what this method actually does.
If - as suggested here - it returns the path to the XML file being processed, you can use the XPath 2.0 base-uri() or document-uri() functions to do the same.

xsl use-character-maps eqivalent in xsl 1.0

I have a xsl 2.0 stylsheet which uses xsl 2.0 specific enhancements. I am now trying to move templates in xsl 1.0 as I have some restrictions in using xsl2.0. When I am running my xsl 1.0 templates I am getting some encoding related errors.
I wanted to understand what is the equivalent of use-character-maps in xsl 1.0.
Thanks
Character maps are a new feature in XSLT 2.0, there is no equivalent feature in XSLT 1.0. However if you want to output a certain entity or character reference in XSLT 1.0 then disable-output-escaping as in e.g.
<xsl:text disable-output-escaping="yes"><![CDATA[ ]]></xsl:text>
might suffice, as long as the transformation result is serialized. In fact, disable-output-escaping use is a feature in XSLT 1.0 supposed to be replaced by character map use in XSLT 2.0.
If you are getting "encoding related errors" then it might be worth finding and eliminating the root cause of those errors, rather than trying patch around them with character maps or disable-output-escaping.

How to use an expression in xsl:include element in an XSLT processing

I need to include an XSLT that exists in 2 variants, depending on a param value.
However, it's seems to be not possible to write an expression in the href attribute of the xsl:include element. My last trial looks like that:
< xsl:param name="ml-fmt" select="mono"/>
...
< xsl:include href="{$ml-fmt}/format.xsl"/>
The XSLT engine used is Saxon 9.2.0.6
Have anybody an idea about how I could do something close to that ?
As Dimitre has said you can't do it, but you can generate the XSLT file from scratch or slightly modify an existing XSLT file by inserting the node in the code preparing the transformation.
You can't.
If you know all possible xslt stylesheet modules to be included, you could use the xsl:use-when attribute in order to selectively include only some of them. However, xsl:use-when has its own limitations. To quote the XSLT 2.0 Spec:
"Any element in the XSLT namespace may have a use-when attribute whose value is an XPath expression that can be evaluated statically".
There is a way to achieve dynamic inclusion, but it requires some non-XSLT initialization:
The code (think C# or Java or ... your programming language) that invokes the transformation, can edit the DOM of the loaded (as XML) XSLT stylesheet and can set the value of the href attribute of any <xsl:import> element to the desired URL.

preproccesing in XSLT

is it at all possible to 'pre-proccess' in XSLT?
with preprocessing i mean updating the (in memory representation) of the source tree.
is this possible, or do i need to do multiple transforms for it.
use case:
we have Docbook reference manuals for out clients but for certain clients these need different 'skins' (different images etc). so what i was hoping to do is transform the image fileref path depending on a parameter. then apply the rest of the normal Docbook XSL templates.
Expanding on Eamon's answer...
In the case of either XSLT 1.0 or 2.0, you'd start by putting the intermediate (pre-processed) result in an <xsl:variable> element, declared either globally (top-level) or locally (inside a template).
<xsl:variable name="intermediate-result">
<!-- code to create pre-processed result, e.g.: -->
<xsl:apply-templates mode="pre-process"/>
</xsl:variable>
In XSLT 2.0, the value of the $intermediate-result variable is a node sequence consisting of one document node (was called "root node" in XSLT/XPath 1.0). You can access and use it just as you would any other variable, e.g., select="$intermediate-result/doc"
But in XSLT 1.0, the value of the $intermediate-result variable is not a first-class node-set. Instead, it's something called a "result tree fragment". It behaves like a node-set containing one root node, but you're restricted in how you can use it. You can copy it and get its string-value, but you can't drill down using XPath, as in select="$intermediate-result/doc". To do that, you must first convert it to a first-class node-set using your processor's node-set() extension function. In Saxon 6.5, libxslt, and 4xslt, you can use exsl:node-set() (as in Eamon's answer). In MSXML, you'd need to use msxsl:node-set(), where xmlns:msxsl="urn:schemas-microsoft-com:xslt", and in Xalan, I believe it's called xalan:nodeset() (without the hyphen, but you'll have to Google for the namespace URI). For example: select="exsl:node-set($intermediate-result)/doc"
XSLT 2.0 simply abolished the result tree fragment, making node-set() unnecessary.
This is not possible with standards compliant XSLT 1.0. It is possible in every actual implementation I've used, however. The extensions with which to do that differ by engine, however. It is also possible in standard XSLT 2.0 (which is in any case much easier to work with - so if you can, just use that).
If your xslt processor supports EXSLT, the exsl:node-set() function does what you're looking for. msxml has an identically named extension function as well (but with a different namespace uri, the functions are unfortunately not trivially compatible).
Since you are trying to generate slightly different output from the same DocBook XML source, you might want to look into the "profiling" (conditional markup) support in DocBook XSL stylesheets. See Chapter 26 in DocBook XSL: The Complete Guide by Bob Stayton:
Profiling is the term used in DocBook
to describe conditional text.
Conditional text means you can create
a single XML document with some
elements marked as conditional. When
you process such a document, you can
specify which conditions apply for
that version of output, and the
stylesheet will include or exclude the
marked text to satisfy the conditions.
This feature is useful when you need
to produce more than one version of a
document, and the versions differ in
minor ways.
For example, to use different images for, say, Windows and Mac versions of the same document, you might have a DocBook XML fragment like this:
<figure>
<title>The Foo dialog</title>
<mediaobject>
<imageobject os="windows">
<imagedata fileref="screenshots/windows/foo.png"/>
</imageobject>
<imageobject os="mac">
<imagedata fileref="screenshots/mac/foo.png"/>
</imageobject>
</mediaobject>
</figure>
Then, you would use the profiling-enabled versions of the DocBook XSL stylesheets with the profile.os parameter set to windows or mac.
Maybe you should use XSLT "OOP" methods here. Put all the common templates to all clients in a stylesheet, and create an stylesheet for each client with specific templates overriding common ones. Import the common stylesheet within the specific ones with xsl:import, and you'll do only one processing by calling the stylesheet corresponding to a client.

Get file name using xsl

How can I get the file name using xsl 1.0?
I tried
<xsl:value-of select="base-uri()" />
but got "Fatal Error! Could not find function: base-uri"
base-uri() is a standard XPath 2.0 function, so when running XSLT 1.0 this function will be unavailable.
In XSLT 1.0 the filename (of what?) may be passed as a parameter for the transformation.
Do note that it isn't always possible to produce a filename for a stylesheet or for an XML document -- either or both may be residing in memory without an associated file.
It is not clear from the problem which filename must be produced.
Here is how to find filenames in XPath 2.0 / XSLT 2.0:
The filename of the current document:
base-uri()
The filename of the current stylesheet module:
base-uri(document(''))
There is no such XPath function, or XSLT extension to XPath function to do this in XSLT v1/XPath v1.
It is quite possible for there to be no file, and even if there is no reason for the XSLT engine to have that file name (consider loading the file content into a buffer, parsing the buffer into a DOM and then passing the DOM to the XSLT processor).
You will need to pass the filename into the processor to be available as a parameter in the transform.