Reputation: 3874
Consider this simple xml element example:
<parent foo="1" bar="2" foobar="3">
<child/>
</parent>
In the xsl file, I am in the context of "parent" (i.e. within the <template match="parent">). I want to select a node set (in the example, only one attribute) based upon a string variable. For example i want to select a node-set which matches $attribute-name. I'll show my failed xsl example and you will probably understand what i'm trying to do.
<xsl:template match="parent">
<xsl:call-template name="print-value-of">
<xsl:with-param name="attribute-type" select="'foo'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="print-value-of">
<xsl:param name="attribute-type"/>
<xsl:value-of select="$attribute-type"/>
</xsl:template>
This prints the output:
foo
What I first INTENDED it to do (but I realize that this is not what it should do) is:
I.e. what I wanted it to print was:
1
THE QUESTION: How can I achieve this behaviour?
Notice: I am aware of the fact that I, in this simple case, could pass the actual attribute node as a parameter (i.e. <xsl:with-param name="attribute" select="foo"/>). But that is not the solution I am searching for. I need to pass only information about the attribute type (or attribute name if you'd prefer to call it that)
What I am actually trying to do is creating a general function template which can:
<EDIT>
I can only use XSLT 1.0, so 1.0 solutions are much preferred!
</EDIT>
<EDIT2>
A follow-up question on a similar theme: Is it also possible to create attributes of a with the name/type specified by a string variable? I.e.
<xsl:attribute name="$attribute-type"/>
Doing it like the line above results in $attribute-type being the literal name of the attribute in the xml output. Instead I would like it, again it to evaluate the variable and give the evaluated value as the name.
</EDIT2>
Upvotes: 4
Views: 4987
Reputation: 338376
This selects an attribute with the name of 'foo'
.
<xsl:call-template name="print-value-of">
<xsl:with-param name="attribute-type" select="@*[name() = 'foo']"/>
</xsl:call-template>
<xsl:template name="print-value-of">
<xsl:param name="attribute-type"/>
<xsl:value-of select="."/>
</xsl:template>
Alternatively, you can leave the <xsl:call-template>
like it is and do the change in your template:
<xsl:template name="print-value-of">
<xsl:param name="attribute-type"/>
<xsl:value-of select="@*[name() = $attribute-type]"/>
</xsl:template>
In any case, unless this was only a synthetic example, all of the above is a quite expensive way of saying:
<xsl:value-of select="@*[name() = $attribute-type]"/>
EDIT:
To create attributes with a dynamic name, use:
<xsl:attribute name="{$attribute-type}">
<xsl:value-of select="$some-value-or-expression" />
</xsl:attribute>
Note that the curly braces make the XSLT-processor evaluate their contents (in attribute values only).
You should make sure that $attribute-type
contains a string that adheres to the XML naming rules. And you should think about renaming the variable to $attribute-name
, because that's what it is.
Upvotes: 4