Jan Toman
Jan Toman

Reputation: 11

apply-templates not working with included file

I have a problem with xsl:include and xsl:apply-templates. I am doing some experiments with dynamic QName in xsl:call-template and I found a way how to do it but... it works only "inline" and not in included file.

If I do this, it works good (one file - file.xsl) - it show text "test" from match template:

<xsl:variable name="template" select="document('')/*/xsl:template"/>

<xsl:template match="xsl:template[@name='test']" name="test">
    test
</xsl:template>

<xsl:template match="root">
    <xsl:apply-templates select="$template[@name = $show]"/>
</xsl:template>

($show = 'test')

But, if I put first part to different file, e.g. template.xsl and then I will call it with xsl:include, it does NOT work. I don't have idea why.

<xsl:variable name="template" select="document('')/*/xsl:template"/>

<xsl:include href="template.xsl" />

<xsl:template match="root">
    <xsl:apply-templates select="$template[@name = $show]"/>
</xsl:template>

Is there anybody who can help me with that please? xsl:include should put content of filename.xsl to parent template but it looks like it didn't

Note: I have XSLT 1.0

Edit 2015-12-10: Thank you guys for pointing to a problem. I am setting path to document('') dynamically now and it works like a charm! Problem was obviously on that blank document(''), thank you very much Michael and others.

<xsl:variable name="path"><xsl:value-of select="$show"/>.xsl</xsl:variable>
<xsl:variable name="templatePath" select="document($path)/*/xsl:template"/>
...
...
<xsl:template match="root">
    <xsl:apply-templates select="$template[@name = $show]"/>
</xsl:template>

Upvotes: 1

Views: 599

Answers (1)

Michael Kay
Michael Kay

Reputation: 163595

The reason that it doesn't work is that the expression

document('')/*/xsl:template

only selects xsl:template elements in the containing document.

The design pattern you are using is essentially a reinvention of the first (XSLT 1.0) version of Dimitre Novatchev's FXSL. I suggest you read up on that. IIRC, Dimitre's approach doesn't match xsl:template elements, but rather on elements whose names correspond to the names of the templates that you want to execute:

<xsl:variable name="names-fragment">
  <A/>
  <B/>
</xsl:variable> 

<xsl:variable name="names" select="exslt:node-set($names-fragment)"/>

<xsl:template name="A" match="A">
    <xsl:call-template name="B"/>
</xsl:template>

<xsl:template name="B" match="B">
    <xsl:param name="target"/>
    <xsl:apply-templates select="$names/*[name()=$target]"/>
</xsl:template>

Here the variable $names is accessible in all stylesheet modules.

Of course, all this tomfoolery becomes unnecessary with higher-order functions in XSLT 3.0.

Upvotes: 0

Related Questions