godpepper
godpepper

Reputation: 11

<xsl:value-of> doesn't work in a template

I spent 2 hours searching for help on Internet, but I didn't find any answer...

I hope you could :)

So, my xslt file is following (simplified) :

<?xml version="1.0" encoding="utf-8" ?>
   <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:param name="basename"/>
    <xsl:param name="purpose"/>
    <xsl:param name="xml_input_path"/>
    <xsl:param name="self"/>

    <xsl:template match="testspec">
        <xsl:call-template name="call_commands"/>
    </xsl:template>

    <xsl:template name="call_commands">
        <xsl:variable name="root" select="document($xml_input_path)/testspec"/>
        <xsl:for-each select="$root//command">
            <xsl:sort select="."/>
            <xsl:variable name="current" select="."/>
            <xsl:apply-templates select="document($self)/xsl:stylesheet/xsl:template[@name = $current/@label]"/>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="TOTO_short">
        <xsl:text>Fonction TOTO :</xsl:text>
        <xsl:variable name="dda" select="'b'"/>
        <xsl:copy-of select="$dda"/>
    </xsl:template>

    <xsl:template name="TATA_interrupt">
                Fonction TATA :
        <xsl:variable name="v1_name" select="'NaN'"/>
        <xsl:value-of select="$v1_name" />
    </xsl:template>
</xsl:stylesheet>

Here is my input Xml :

<testspec>
   <command label="TOTO_short"/>
   <command label="TATA_interrupt"/>
   <command label="TOTO_short"/>
   <command label="TATA_interrupt"/>
</testspec>

My problem is following : in templates TOTO_short and TATA_short, I would like to define 2 variables and display their values...

But it doesn't work!

Can you help me please to understand where it comes from?

Thanks a lot in advance :)

Arnaud

Upvotes: 1

Views: 950

Answers (1)

Tim C
Tim C

Reputation: 70618

The problem is with this rather crazy looking line

<xsl:apply-templates select="document($self)/xsl:stylesheet/xsl:template[@name = $current/@label]"/>

It looks like you are trying to call the named template with the name equal to whatever the current label attribute is. But to call a named template, you must use xsl:call-template. For your current xsl:apply-templates to find anything, you would need a template like so:

<xsl:template match="xsl:template[@name='TOTO_short']">
    <xsl:call-template name="TOTO_short" />
</xsl:template>

This is really not the way to go about things! The reason your named templates appear to work is because the built-in templates in XSLT are being used here. When it can't find a matching template like above, it will simply output the text of the element.

I don't really see the need for such a complicated approach. Instead of your current xsl:for-each, you can simply do this:

<xsl:apply-templates select="$root//command" />

And then you have a matching template, like so:

<xsl:template match="command[@label='TOTO_short']">
    <xsl:text>Fonction TOTO :</xsl:text>
    <xsl:variable name="dda" select="'b'"/>
    <xsl:copy-of select="$dda"/>
</xsl:template>

Try this XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:param name="basename"/>
    <xsl:param name="purpose"/>
    <xsl:param name="xml_input_path" select="'C:\Users\Tim Case\Documents\Test.xml'" />
    <xsl:param name="self"/>

    <xsl:template match="testspec">
        <xsl:call-template name="call_commands"/>
    </xsl:template>

    <xsl:template name="call_commands">
        <xsl:variable name="root" select="document($xml_input_path)/testspec"/>
        <xsl:apply-templates select="$root//command" />
    </xsl:template>

    <xsl:template match="command[@label='TOTO_short']">
        <xsl:text>Fonction TOTO :</xsl:text>
        <xsl:variable name="dda" select="'b'"/>
        <xsl:copy-of select="$dda"/>
    </xsl:template>

    <xsl:template match="command[@label='TATA_interrupt']">
                Fonction TATA :
        <xsl:variable name="v1_name" select="'NaN'"/>
        <xsl:value-of select="$v1_name" />
    </xsl:template>
</xsl:stylesheet>

In fact, I am not sure why you are passing the path to the XML as a parameter here. You could infact simplify the XSLT to this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:param name="basename"/>
    <xsl:param name="purpose"/>

    <xsl:template match="testspec">
        <xsl:apply-templates select="command" />
    </xsl:template>

    <xsl:template match="command[@label='TOTO_short']">
        <xsl:text>Fonction TOTO :</xsl:text>
        <xsl:variable name="dda" select="'b'"/>
        <xsl:copy-of select="$dda"/>
    </xsl:template>

    <xsl:template match="command[@label='TATA_interrupt']">
                Fonction TATA :
        <xsl:variable name="v1_name" select="'NaN'"/>
        <xsl:value-of select="$v1_name" />
    </xsl:template>
</xsl:stylesheet>

Upvotes: 2

Related Questions