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"/>
Related
Please forgive the poor nomenclature in this, probably why I'm struggling to google an answer.
Basically I am asking if parameter tunneling from xslt 2.0 has any analogue in 1.0, or if there is a clever way to get 'some way there'. I'm using msxsl
Suppose I have a template like so:
<xsl:template name="outer">
<xsl:apply-templates>
<xsl:with-param name="x" select="y"/>
</xsl:apply-templates>
</xsl:template>
If the apply-templates call gets picked up directly by a template that knows about the parameter then all is good, but suppose we have some general templates to ignore certain elements and process their children:
<xsl:template match="tag_to_ignore">
<xsl:apply-templates/>
</xsl:template>
if these are 'hit' OR when the tag_to_ignore is not explicitly matched and XSLT does its default apply templates to children behaviour
the parameters are 'lost'
is there anyway to tell a template to 'accept' all parameters it was passed and pass them down?
(ie the real code there are many, many, params that could come in and potentially need to be passed out, trying to avoid a maintenance issue of having to accept every possible para and explicitly pass it on)
In XSLT 2.0 you can use tunnel parameters but in XSLT 1.0 there is no such feature.
Actually, I had a similar issue before I heard about tunnelling parameters and solved it by adding the same parameters to the one-off template, then passing it back out in that apply-templates. For instance, in your case
<xsl:template match="tag_to_ignore">
<xsl:param name="x"/>
<xsl:apply-templates>
<xsl:with-param name="x" select="$x" />
</xsl:apply-templates>
</xsl:template>
I THINK this will work in XSLT 1.0, but I'm fairly new to all this myself.
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.
I'm working with some third-party XSLT that makes heavy use of attribute sets for transforming XML to various forms of XSL:FO. Example:
notes.xsl:
<xsl:template match="note">
<fo:block xsl:use-attribute-sets="noteAttrs">
<!-- This is a pretty big template with lots of xsl:choose/xsl:if/etc. -->
</fo:block>
<xsl:template>
<xsl:attribute-set name="noteAttrs">
<xsl:attribute name="margin-left">10px</xsl:attribute>
<xsl:attribute name="margin-right">8px</xsl:attribute>
<xsl:attribute name="margin-top">5px</xsl:attribute>
<xsl:attribute name="font-size">10pt</xsl:attribute>
<!-- several other attributes -->
</xsl:attribute>
The idea is that I import this XSLT, redefining the attribute sets as I see fit. If I just need a different font size for a given .fo document...
<xsl:import href="notes.xsl"/>
<xsl:attribute-set name="noteAttrs">
<xsl:attribute name="font-size">12pt</xsl:attribute>
</xsl:attribute>
The problem is that sometimes I need to flat out remove attributes (i.e. so I inherit from the containing fo:block), or a given fo document is going to be so different that it would be easier to start fresh instead of merge my attribute set with the one from notes.xsl. Is there a way in XSLT 2.0 to do that without reproducing the entire template for note and specifying a different attribute set on the fo:block? I guess I'm looking to be able to do something like this:
<xsl:import href="notes.xsl"/>
<xsl:attribute-set name="noteAttrs" merge_with_imported_attr_set="false">
<xsl:attribute name="font-size">12pt</xsl:attribute>
</xsl:attribute>
I can't switch to an XSLT 3.0 processor immediately, but if there's something new in 3.0 that enables this, I'd love to know about it.
Thanks!
Attribute sets are not very widely used and to answer your question I had to look at the spec to refresh my memory. I don't think there is any way of achieving what you are wanting; you can't really override an attribute set in an importing stylesheet, you can only supplement it. In a well-designed XML vocabulary there is usually an attribute value you can set that is equivalent to omitting the attribute, but if that's not the case then you are stuck.
Say you have an XSLT which is currently in use for a myriad of cases. Given that it does not currently have any <xsl:template match="/">; would adding the following template interfere with anything?
<xsl:template match="/">
<xsl:choose>
<xsl:when test="some condition which is only true for new cases"></xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Reason I'm asking is that we have a huge XSLT file which is currently in use and should not be broken, but we need to add some new transformations to it. Making some decisions on the root would make things a lot easier and cleaner.
I was just told that if there is no template matching /, then a default template equivalent to <xsl:apply-templates /> will be applied. So, just wanting to check if my understand is correct, and that this then (as long as the test is only true for new cases) would not break any existing transformations.
That's correct, you can handle your conditions within the root template "/" and just apply-templates for the "normal" treatement.
But check existing root templates matching "/" - maybe it is already doing more than just apply the next templates.
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.