1

I am trying to make a named template or function where I an pass in a node name and it will select that as the last level of a xpath expression. But all it returns is the string I pass in as a param. In the below example the value returned is "name"

XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes"></xsl:output>

    <xsl:template name="get-prefered">
        <xsl:param name="field-name"/> 

        <xsl:variable name="vCondition" select="name"/>
        <xsl:variable name="x" select="sources/source[@type='C']/$field-name"/>
        <xsl:value-of select="$x"></xsl:value-of>
    </xsl:template>

    <xsl:template match="/">
        <xsl:call-template name="get-prefered">
            <xsl:with-param name="field-name">name</xsl:with-param>
        </xsl:call-template>
        </xsl:template>
</xsl:stylesheet>

INPUT XML:

<?xml version="1.0" encoding="UTF-8"?>
<sources>
    <source type='C'>
        <name>Joe</name>
        <age>10</age>
    </source>
    <source type='B'>
        <name>Mark</name>
        <age>20</age>
    </source>
</sources>
Alex
  • 1,891
  • 3
  • 23
  • 39

3 Answers3

6

change

<xsl:variable name="x" select="sources/source[@type='C']/$field-name"/>

to

<xsl:variable name="x" select="sources/source[@type='C']/*[name()=$field-name]"/>

it returns:

Joe
Joel M. Lamsen
  • 7,143
  • 1
  • 12
  • 14
  • Is there also a solution when you want to pass a set of alternatives like `name1|name2|name3`? It would not make much sense in this example, but I'm fighting that problem. – U. Windl Jun 06 '23 at 09:57
3

The problem here:

select="sources/source[@type='C']/$field-name"

is that the variable $field-name contains a string, not a location path - so that the expression expands to:

select="sources/source[@type='C']/'name'"

If you're using an XSLT 2.0 processor, then you are likely to have access to an evaluate() function that can convert a string into a path, e.g. http://www.saxonica.com/documentation9.4-demo/html/extensions/functions/evaluate.html Otherwise you'll need to use some other method - for example, the one shown by Joel M. Lamsen in his answer.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
1

I assume that your named template want to process the entire document, Then xslt is like this ...

<xsl:output indent="yes"></xsl:output>

<xsl:template name="get-prefered">
    <xsl:param name="field-name"/> 

    <xsl:variable name="vCondition" select="$field-name/name"/>
    <xsl:variable name="x" select="$field-name/sources/source[@type='C']/name"/>
    <xsl:value-of select="$x"></xsl:value-of>
</xsl:template>

<xsl:template match="/">
    <xsl:call-template name="get-prefered">
        <xsl:with-param name="field-name" select="."></xsl:with-param>
    </xsl:call-template>
    </xsl:template>

  • Not exactly. I want to be able to pasd in the last level of the xpath (in this simplified example the only valid choices are name and age) and it return one value. – Alex Aug 18 '14 at 05:17