Reputation: 532
my xml file
...
<element1>
<year>1</year>
<month>5</month>
<days>3</days>
</element1>
<element2>
<year>2</year>
<month>4</month>
<days>5</days>
</element2>
...
my xsl-fo template
<fo:block>
<xsl:value-of select="//element1/years"/>
<xsl:text> years </xsl:text>
<xsl:value-of select="//element1/month"/>
<xsl:text> month </xsl:text>
<xsl:value-of select="//element1/days"/>
<xsl:text> days </xsl:text>
</fo:block>
...
<fo:block>
<xsl:value-of select="//element2/years"/>
<xsl:text> years </xsl:text>
<xsl:value-of select="//element2/month"/>
<xsl:text> month </xsl:text>
<xsl:value-of select="//element2/days"/>
<xsl:text> days </xsl:text>
</fo:block>
As you can see, here is a similar blocks of code. How can i simplify this expressions ? What kind of template should use ?
I wrote a template like this
<xsl:template match="element1">
<xsl:value-of select="years"/>
<xsl:text> years </xsl:text>
<xsl:value-of select="month"/>
<xsl:text> month </xsl:text>
<xsl:value-of select="days"/>
<xsl:text> days </xsl:text>
</xsl:template>
and used it
<fo:block>
<xsl:apply-templates select="element1"/>
</fo:block>
but its not applicable to element2...
Upvotes: 0
Views: 49
Reputation: 2167
Given XML (credits go to @michael.hor257k):
<parent>
<element1>
<year>1</year>
<month>5</month>
<days>3</days>
<hour>12</hour>
<minute>32</minute>
</element1>
<element2>
<year>2</year>
<month>4</month>
<days>5</days>
<hour>0</hour>
</element2>
</parent>
I. Match multiple elements in pattern for template
<xsl:template match="element1 | element2">
<fo:block>
<xsl:value-of select="year"/>
<xsl:text> years </xsl:text>
<xsl:value-of select="month"/>
<xsl:text> month </xsl:text>
<xsl:value-of select="days"/>
<xsl:text> days </xsl:text>
</fo:block>
</xsl:template>
II. Call-Teamplate
<xsl:template match="element1">
<xsl:call-template name="renderOutput"/>
</xsl:template>
<xsl:template name="renderOutput">
<fo:block>
<xsl:value-of select="year"/>
<xsl:text> years </xsl:text>
<xsl:value-of select="month"/>
<xsl:text> month </xsl:text>
<xsl:value-of select="days"/>
<xsl:text> days </xsl:text>
</fo:block>
</xsl:template>
[by default the context node within call-template picks up the context node of caller! Not needed but also ok, go ahead with <xsl:with-param name="this" select="."/>
and <xsl:value-of select="$this/year"/>
]
Upvotes: 1
Reputation: 116992
Well, given:
<parent>
<element1>
<year>1</year>
<month>5</month>
<days>3</days>
</element1>
<element2>
<year>2</year>
<month>4</month>
<days>5</days>
</element2>
</parent>
you could do:
<xsl:template match="parent">
<fo:wrapper>
<xsl:for-each select="*">
<fo:block>
<xsl:value-of select="year"/>
<xsl:text> years </xsl:text>
<xsl:value-of select="month"/>
<xsl:text> months </xsl:text>
<xsl:value-of select="days"/>
<xsl:text> days </xsl:text>
</fo:block>
</xsl:for-each>
</fo:wrapper>
</xsl:template>
to get:
<fo:wrapper>
<fo:block>1 years 5 months 3 days </fo:block>
<fo:block>2 years 4 months 5 days </fo:block>
</fo:wrapper>
i don't need to select all elements, i just want to apply this kind of template to elements with similar childs, in deferent places
In such case, you could call a named template - for example:
<xsl:template match="element1">
<xsl:call-template name="duration"/>
</xsl:template>
...
<xsl:template match="element1">
<xsl:call-template name="duration"/>
</xsl:template>
...
<xsl:template name="duration">
<fo:block>
<xsl:value-of select="year"/>
<xsl:text> years </xsl:text>
<xsl:value-of select="month"/>
<xsl:text> months </xsl:text>
<xsl:value-of select="days"/>
<xsl:text> days </xsl:text>
</fo:block>
</xsl:template>
Upvotes: 1