Using a parameter passed into xslt stylesheet - xslt

I am using Saxon to perform a transformation of an XML document in my .NET application. I am passing in a parameter to my xslt document but I have no idea how to use it in my template.
Here is what I have done so far:
var zipcode = _db.AXCustomers.FirstOrDefault(x => x.ACCOUNTNUM == accNo).ZIPCODE;
transformer.SetParameter(new QName("CustomerZipCode"), new XdmAtomicValue(zipcode));
Then in my xslt document I am specifying the parameter like so:
<xsl:template match="/">
<xsl:param name="CustomerZipCode" />
But when I try to use the parameter, nothing appears. I am using it like so:
<xsl:value-of select="substring-before($CustomerZipCode, ' ')"/>
But nothing is output even though my zipcode does contain a value

You are using xsl:param inside a xsl:template element, it means that the param is for the template. The parameter you are passing from the .net code is a transformer parameter and related xsl:param must be placed at the top level of the stylesheet, into the xsl:stylesheet element.

Related

Passing a node as parameter to a XSL stylesheet

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.

Retrieving sub-element attribute's value based on uniq-key with xslt ant

My xml looks something like this:
<someRoot
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../my.xsd">
<position name="quality">
<db>
<server name="blah-blah" type="xyz"/>
</db>
<some-more-element value="12345"/>
<my-needy-element>
<my-needy-sub-element name="uk1"
value="a,b,c"
more-attr="some-val"/>
<my-needy-sub-element name="uk2"
value="x,b,y,c"
more-attr="some-diff-val"/>
</my-needy-element>
</position>
</someRoot>
Retrieving say my single db-server name works after I do xmlproperty & samy something like : ${db.server(name)}. Now I am trying to retrieve value for sub elements - but it always
gives me all row values matching it. eg: ${my-needy-element.my-needy-sub-element(more-attr)} will print some-val,some-diff-val . How do I get attribute value matching
to paricular unique name , something like {my-needy-element.my-needy-sub-element(more-attr) with name="uk1"}
Adding editing comment: Is there any way even if I use xslt ant-task by passing 'uk1' & get required sub-element attribute value? with xsl:if or key match
Amending more:
Have tried with xsl & then an xslt ant , but it doesnot seem to give what I am looking for:
<xsl:template match="/someRoot/my-needy-element/my-needy-sub-element">
<someRoot>
<xsl:key name="my-needy-sub-element" match="text()" use="#name"/>
<xsl:apply-templates select="key('name',$xslParamPassed)"/>
</someRoot>
</xsl:template>
thanks,
You can't do this with xmlproperty but you might consider the third-party xmltask which lets you use full-fledged XPath expressions:
<xmltask source="file.xml">
<copy path="/someRoot/position/my-needy-element/my-needy-sub-element[#name='uk1']/#more-attr"
property="more.attr" />
</xmltask>
<echo>${more.attr}</echo>

How to get template name inside template

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"/>

Fallback behavior when an XSLT extension function is not present

Is it possible to provide fallback behavior when a function implemented in an external XSLT object is not present (in XSLT 1.0)?
Right now, I have something similar to
<xsl:template match="an-element">
<xsl:value-of select="external-ns:ExternalFunction(.)" />
</xsl:template>
However, it's possible to generate content that makes sense if external-ns is not available, it just won't be as smart. So, I'd like to have something like
<!-- (pseudo) -->
<xsl:template match="an-element">
<xsl:try>
<xsl:value-of select="external-ns:ExternalFunction(.)" />
<xsl:catch>
<!-- do something else with the node -->
</xsl:catch>
</xsl:try>
</xsl:template>
I'm aware of xsl:fallback and element-available() but these seem to be only for elements, not functions. Is there any way to achieve this?
From http://www.w3.org/TR/xslt#function-function-available
Function: boolean function-available(string)
The argument must evaluate to a string
that is a QName. The QName is expanded
into an expanded-name using the
namespace declarations in scope for
the expression. The function-available
function returns true if and only if
the expanded-name is the name of a
function in the function library. If
the expanded-name has a non-null
namespace URI, then it refers to an
extension function; otherwise, it
refers to a function defined by XPath
or XSLT.

Xslt transform on special characters

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.