[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] How can one get the name of a template or function?


Subject: Re: [xsl] How can one get the name of a template or function?
From: John Lumley <John.Lumley@xxxxxxxxxxxxxx>
Date: Tue, 12 Mar 2013 21:53:57 +0000

This is one of the joys of XSLT being a homoiconic language. It can be comparatively trivial to consistently modify an XSLT program with XLST - in this case to add some tracing activities. Another example arose recently for me where in SaxonCE, the DOM element tree doesn't have namespaces, but does have QNames. So @z:attr won't be recognised, but @*[name()='z:attr'] will be. So a simple XSLT preprocessor containing a match:

<xsl:template match="xsl:*/@select">
<xsl:attribute name="{name()}" select="replace(.,'@(\i\c*:\i\c*)','@*[name()=''$1'']')"/>
</xsl:template>


should be able to consistently change the source.

Another On 12/03/2013 21:27, Philip Fearon wrote:
A crude approach for collecting data on invoked templates, is to use a
'meta' XSLT stylesheet that modifies the XSLT you're interested in
collecting data on. This could insert xsl:message instructions in each
target template. You then just need to use this modified stylesheet on
sample data.

The XSLT might look something like this (this version not tested):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:pxsl="http://qutoric.com/proxy-for-xsl">

<xsl:namespace-alias stylesheet-prefix="pxsl" result-prefix="xsl"/>

<xsl:output method="xml" indent="no"/>

<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<xsl:template

match="xsl:template">
<xsl:choose>
<xsl:when test="empty(*)">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>

<xsl:copy>
<xsl:apply-templates select="@*| xsl:param"/>

<xsl:apply-templates select="node() except xsl:param"/>
<xsl:variable name="msg" as="xs:string*">
<xsl:for-each select="@*">
<xsl:if test="name(.) = ('match','mode','name')">
<xsl:value-of select="concat(' ', name(.),': ',.)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:text>&#10;</xsl:text>
<pxsl:message>Template-Signature: <xsl:value-of select="msg"/></pxsl:message>
<xsl:text>&#10;</xsl:text>

</xsl:copy>
</xsl:otherwise>
</xsl:choose>

</xsl:template>

</xsl:stylesheet>

-------------

Phil Fearon

On Fri, Mar 1, 2013 at 3:50 AM, John Laurence Poole<jlpoole56@xxxxxxxxx> wrote:
I'm resurrecting an old 2009 topic regarding
getting the name of a template.

I followed Michael's suggestion below and have
successfully written an extension function that
produces the names of the template in instances
where the template is invoke through the
xsl:call-template mechanism.

I'd be happy to provide a how-to on how I accomplished this along with
demonstration files if someone would like them; I suspect this is a
very esoteric area and there would not be any takers on my offer.

What I would like to have is the ability to get
the name of a template in instances where the
template is invoked via the match mechanism:
xsl:apply-templates.  This would be for instances where
the template has a name attribute, e.g. name="template_ABC".  I tried
invoking my function similar to that below in a match situation and
null was returned despite the fact that the template that matched had
a name attribute.

Any suggestions on how to approach this?  I'm new to studying the
internals of Saxon, but believe there must be some place where
information about the templates is stored to be accessed by the parser
for the match facility and that extending the properties of the
storage model to include a name attribute in instances where a
template does have a name attribute would be the way toapproach this.
Maybe I'm barking up the wrong tree and the matching mechanism is not
what I'm imagining?

Thanks,

John Poole


here's the message I'm following up on:


On 2009-02-11 11:57:49 Michael Kay posted to this list:

If you're prepared to grovel around the depths of Saxon internals, you can
write an extension function


public static String getTemplateName(net.sf.saxon.expr XPathContext context) { try { return context.getOrigin().getObjectName().getDisplayName(); } catch (Exception err) { return null; } }

and call it without any arguments as xx:getTemplateName(). Not tested. It
will only give the template name if it was invoked using call-template.
Should probably work for function calls as well.

Michael Kay
http://www.saxonica.com/





--
John Lumley MA PhD CEng FIEE
john@xxxxxxxxxxxxxx


Current Thread
Keywords