Search code examples
xsltxslt-2.0

loop without context node change


Need help. Please see my comment in the 'department' template. Here i want to repeat the same processing multiple times (based on $time variable). if I use call-template and pass the current-node, then i can not re-use the already written child template rules. What is good way to achieve this.

XML

   <?xml version="1.0" encoding="UTF-8"?>
  <emp>
    <department name="science">
      <empname>Rob</empname>
      <empno>01</empno>
      <emptype>regular</emptype>
   </department>
  </emp>

XSLT

  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs"
      version="2.0">
      <xsl:param name="times" select="'a1,b1,c1'"></xsl:param>
      <xsl:template match="/">        
          <xsl:apply-templates/>
      </xsl:template>
      <xsl:template match="department">
          <xsl:copy>
              <xsl:copy-of select="@*"></xsl:copy-of>
              <xsl:apply-templates select="empname"/>
              <someelements></someelements>
              <xsl:apply-templates select="empno"/>
              <instances>
              <xsl:for-each select="tokenize($times, ',\s*')">
                  <xsl:variable name="time" select="."/>
                  <iemployee time="{$time}">
                      <!-- I want to repat the the "department" template here -->
                  </iemployee>
              </xsl:for-each>
              </instances>
          </xsl:copy>
      </xsl:template>
      <xsl:template match="empname">
          <employeename>
              <xsl:apply-templates/>
          </employeename>
      </xsl:template>
      <xsl:template match="empno">
          <employeenumber>
              <xsl:apply-templates/>
          </employeenumber>
      </xsl:template>
  </xsl:stylesheet>

output

<department name="science">
<employeename>Rob</employeename>
<someelements/>
<employeenumber>01</employeenumber>
<instances>
    <iemployee time="a1">
        <employeename>Rob</employeename>
        <someelements/>
        <employeenumber>01</employeenumber>
    </iemployee>
    <iemployee time="b1">
        <employeename>Rob</employeename>
        <someelements/>
        <employeenumber>01</employeenumber>
    </iemployee>
    <iemployee time="c1">
        <employeename>Rob</employeename>
        <someelements/>
        <employeenumber>01</employeenumber>
    </iemployee>
</instances>


Solution

  • I think you need a second template with a different mode:

      <xsl:template match="department">
          <xsl:copy>
              <xsl:copy-of select="@*"></xsl:copy-of>
              <xsl:apply-templates select="." mode="content"/> 
              <instances>
              <xsl:variable name="dep" select="."/>
              <xsl:for-each select="tokenize($times, ',\s*')">
                  <xsl:variable name="time" select="."/>
                  <iemployee time="{$time}">
                      <xsl:apply-templates select="$dep" mode="content"/>
                  </iemployee>
              </xsl:for-each>
              </instances>
          </xsl:copy>
      </xsl:template>
    
      <xsl:template match="department" mode="content">
               <xsl:apply-templates select="empname"/>
              <someelements></someelements>
              <xsl:apply-templates select="empno"/>
      </xsl:template>