guesswho
guesswho

Reputation: 532

template to similar fields in xslt

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

Answers (2)

uL1
uL1

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

michael.hor257k
michael.hor257k

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

Related Questions