I am trying to parametrize a path to include a xslt file into other, I have been trying with the way described here:
<xsl:param name="basedir" />
<xsl:include href="{$basedir}/team-menu.xsl" />
and call to the xslt doing:
xsltproc --stringparam basedir style example.xslt example.xml
But no way. I am not abel to do it work. It seems like if the xsl:output element was related because the only way I could make it "work" was this:
<xsl:include href="the/path/to/file/team-menu.xsl" />
<xsl:output method="xml" indent="yes"/>
<xsl:param name="basedir" />
I mean... putting the param after the output and the include before. Big problem: I can´t use the variable basedir.
Any way to do this??
Thank you in advance.
In XSLT 3.0 you can do this provided the parameters are declared as static, which means the values have to be supplied at compile time. You also need to prefix the attribute with "_":
<xsl:param name="basedir" static="yes"/>
<xsl:include _href="{$basedir}/team-menu.xsl" />
The reason it doesn't work with ordinary variables should be fairly obvious: variable values aren't known until run-time, and you can't start execution until you have found all the source code making up the stylesheet.
What you can do with earlier releases of XSLT, depending on the processor, is to redirect xs:include/xs:import URIs from the API level, for example (on Java) by using a user-supplied URIResolver.
Related
I need to pass a node as a parameter to an XSL stylesheet. The issue is that the parameter gets sent as a string. I have seen the several SO questions regarding this topic, and I know that the solution (in XSLT 1.0) is to use an external node-set() function to transform the string to a node set.
My issue is that I am using eXist DB I cannot seem to be able to get its XSLT processor to locate any such function. I have tried the EXSLT node-set() from the namespace http://exslt.org/common as well as both the Saxon and Xalan version (I think eXist used to use Xalan but now it might be Saxon).
Are these extensions even allowed in the XSLT processor used by eXist? If not, is there something else I can do?
To reference or transform documents from the database, you should pass the path as a parameter to the transformation, and then refer to it using a parameter and variable
(: xquery :)
let $path-to-document := "/db/test/testa.xml"
let $stylesheet :=
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="source" required="no"/>
<xsl:variable name="error"><error>doc not available</error></xsl:variable>
<xsl:variable name="theDoc" select="if (doc-available($source)) then doc($source) else $error"/>
<xsl:template match="/">
<result><xsl:value-of select="$source"/> - <xsl:value-of select="node-name($theDoc/*)"/></result>
</xsl:template>
</xsl:stylesheet>
return transform:transform(<dummy/>,$stylesheet, <parameters><param name="source" value="xmldb:exist://{$path-to-document}"/></parameters>)
As per Martin Honnen's comments I don't think it is possible to pass an XML node via the <parameters> structure of the transform:transform() function in eXist. The function seems to strip away any XML tags passed to it as a value.
As a workaround I will wrap both my input XML and my parameter XML into a root element and pass that as input to the transform function.
I'm using xslt 2.0. Can I have a common xslt file that is imported by two main stylesheets, where one of those outputs html and the other outputs xml?
For example, say I have common.xsl. It transforms xml to xml.
Then I have main_output_xml.xsl. This will import common.xsl and its output format will be xml.
I also have main_output_html.xsl. This will also import common.xsl, but it will have an output format of html.
Is this possible?
As Ken Holman says, the answer is yes, you can do exactly what you are suggesting.
#Nalaka526 if your read the question then you will see that it only demands a "yes" or "no" answer. The only reason my answer is longer is that SO doesn't allow short answers.
Short: "Yes".
Long: use named output.
First, define the different output options at the top level of your XSLT.
"20 Serialization.
...
A stylesheet may contain multiple xsl:output declarations and may include or import stylesheet modules that also contain xsl:output declarations. The name of an xsl:output declaration is the value of its name attribute, if any."
<xsl:output name="text" method="text" indent="no" encoding="utf-8" />
<xsl:output name="default" indent="no" method="html" encoding="utf-8" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" />
Then use one of the defined name methods in your result-document output:
<xsl:result-document href="output_file.txt" format="text">
...
</xsl:result-document>
"19.1 Creating Final Result Trees
...
The xsl:result-document instruction defines the URI of the result tree, and may optionally specify the output format to be used for serializing this tree."
I try to concstruct link with
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="concat('file:///', substring-before('%RolesPath%', 'roles'),'Flores.chm')"/>
</xsl:attribute>
Help
</xsl:element>
but I get error:
File file:///Flores.chm not found
I'm pretty sure, that variable %RolesPath% works fine. I'm using it in code normally. And if I use in code only
<xsl:value-of select="concat('file:///', substring-before('%RolesPath%', 'roles'),'Flores.chm')"/>
I get
file:///C:\Flores\Flores.chm
which is right path. Where I'm doing mistake please?
edit. %RolesPath% stores path to specify folder of program, which works with this code. In my case %RolesPath% stores "C:\Flores\roles\".
To specify my problem. I need open file(Flores.chm) in root folder of program. Program can be install everywhere in PC and prapably only way, how I can get the path is via %RolesPath%.
What you are passing to substring-before() is just a string ('%RolesPath%'). It appears that you are trying to use a Windows environment variable. This isn't going to work the way you're using it.
I think you have 2 options:
Option 1
Pass the value of the environment variable as an xsl:param when you call the stylesheet. This would work in either XSLT 1.0 or 2.0.
You would need the xsl:param:
<xsl:param name="RolesPath"/>
and this is how you would reference it:
<a href="{concat('file:///', substring-before($RolesPath, 'roles'),'Flores.chm')}"/>
Option 2
Use the environment-variable() function. This would only work with an XSLT 3.0 processor, such as Saxon-PE or EE.
Example:
<a href="{concat('file:///', substring-before(environment-variable('RolesPath'), 'roles'),'Flores.chm')}"/>
Here's another example of environment-variable() to show the function actually working:
XSLT 3.0
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<environment-variable name="TEMP" value="{environment-variable('TEMP')}"/>
</xsl:template>
</xsl:stylesheet>
Output (when applied to any well-formed XML)
<environment-variable name="TEMP" value="C:\Users\dhaley\AppData\Local\Temp"/>
Use this shorter expression:
<a href="file:///{substring-before($RolesPath, 'roles')}Flores.chm"/>
where $RolesPath is passed as an external, global parameter to the transformation.
How exactly to pass an external parameter to the transformation varies from one XSLT processor to another -- read your XSLT processor documentation. Some XSLT processors also allow string-typed parameters to be passed to the transformation from a command-line execution utility.
Is it possible to get template name while inside template?
Example:
<xsl:template name="list">
<!-- Get name value (in this case "list") -->
</xsl:template>
As far as I am aware, neither XSLT 1.0 nor XSLT 2.0 offer such a feature.
As Martin says, there's probably no way to do this.
Even if such a capacity existed, surely using it couldn't be any simpler than just defining a variable with the value you want:
<xsl:template name="list">
<xsl:variable name="class" select="'list'" />
and then using that variable where you need it. This also has the benefit that you can change the template name without rewriting all your CSS, or change the class name without rewriting your XSLT.
One of the benefits of the fact that XSLT uses XML syntax is that it's easy to transform stylesheets. Modifying every named template to contain a variable holding the template name is dead easy.
#JLRishe's answer is a good approach. However, there is a trap. Any <xsl:param> must be declared before any <xsl:variable>.
This will not work:
<xsl:template name="foobarsnafu">
<xsl:variable name="foo" value="bar">
<xsl:param name="snafu"/>
But this will:
<xsl:template name="foobarsnafu">
<xsl:param name="snafu"/>
<xsl:variable name="foo" value="bar">
This might be a problem if, for example, you want the default value of your snafu <xsl:param> to be the value of your foo <xsl:variable>. The way around it would be to use <xsl:param> with a default value for your template name, i.e.:
<xsl:template name="foobarsnafu">
<xsl:param name="template_name" select="foobarsnafu"/>
I have an XML document that needs to pass text inside an element with an '&' in it.
This is called from .NET to a Web Service and comes over the wire with the correct encoding &
e.g.
T&O
I then need to use XSLT to create a transform but need to query SQL server through a SP without the encoding on the Ampersand e.g T&O would go to the DB.
(Note this all has to be done through XSLT, I do have the choice to use .NET encoding at this point)
Anyone have any idea how to do this from XSLT?
Note my XSLT knowledge isn’t the best to say the least!
Cheers
<xsl:text disable-output-escaping="yes">&<!--&--></xsl:text>
More info at: http://www.w3schools.com/xsl/el_text.asp
If you have the choice to use .NET you can convert between an HTML-encoded and regular string using (this code requires a reference to System.Web):
string htmlEncodedText = System.Web.HttpUtility.HtmlEncode("T&O");
string text = System.Web.HttpUtility.HtmlDecode(htmlEncodedText);
Update
Since you need to do this in plain XSLT you can use xsl:value-of to decode the HTML encoding:
<xsl:variable name="test">
<xsl:value-of select="'T&O'"/>
</xsl:variable>
The variable string($test) will have the value T&O. You can pass this variable as an argument to your extension function then.
Supposing your XML looks like this:
<root>T&O</root>
you can use this XSLT snippet to get the text out of it:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="root"> <!-- Select the root element... -->
<xsl:value-of select="." /> <!-- ...and extract all text from it -->
</xsl:template>
</xsl:stylesheet>
Output (from Saxon 9, that is):
T&O
The point is the <xsl:output/> element. The defauklt would be to output XML, where the ampersand would still be encoded.