Search code examples
xsltxslt-2.0

Adding Counter/Sequence number to xml field in XSLT


I am using following code to add sequence numbers to /G_HL/S_HL segments but not working. With the following code I am able to populate D_628 with correct sequence but not able populate D_734 in correct sequence.<D_628> and <D_734> value should be populated in sequence. staring with numeric 1 and 0 respectively.

Source XML Updating the Source XML

<M_856>
    <G_HL>
        <S_HL>
            <D_628><D_628/>
            <D_734><D_734/>
            <D_735>O</D_735>
        </G_HL>
        <G_HL>
            <S_HL>
                <D_628><D_628/>
                <D_734><D_734/>
                <D_735>T</D_735>
            </S_HL>
        </G_HL>
        <G_HL>
            <S_HL>
                <D_628><D_628/>
                <D_734><D_734/>
                <D_735>T</D_735>
            </S_HL>
        </G_HL>
        <G_HL>
            <S_HL>
                <D_628><D_628/>
                <D_734><D_734/>
                <D_735>I</D_735>
            </S_HL>
        </G_HL>
        <G_HL>
            <S_HL>
                <D_628><D_628/>
                <D_734><D_734/>
                <D_735>I</D_735>
            </S_HL>
        </G_HL>
    </M_856>

Desired Output

<M_856>
   <G_HL>
      <S_HL>
         <D_628>1<D_628/>
         <D_734>0<D_734/>
         <D_735>O</D_735>
   </G_HL>
   <G_HL>
      <S_HL>
         <D_628>2<D_628/>
         <D_734>1<D_734/>
         <D_735>T</D_735>
      </S_HL>
   </G_HL>
   <G_HL>
      <S_HL>
         <D_628>3<D_628/>
         <D_734>2<D_734/>
         <D_735>T</D_735>
      </S_HL>
   </G_HL>
   <G_HL>
      <S_HL>
        <D_628>4<D_628/>
        <D_734>3<D_734/>
         <D_735>I</D_735>
      </S_HL>
   </G_HL>
   <G_HL>
      <S_HL>
         <D_628>5<D_628/>
         <D_734>4<D_734/>
         <D_735>I</D_735>
      </S_HL>
   </G_HL>
</M_856>

XSLT Using

<xsl:template match="M_856/G_HL/S_HL/D_628">
<xsl:copy>
<xsl:number count="M_856/G_HL/S_HL/D_628" start-at="1" level="any"/>
</xsl:copy>
</xsl:template>
<xsl:template match="M_856/G_HL/S_HL/D_734">
<xsl:copy>
<xsl:number count="M_856/G_HL/S_HL/D_734" start-at="0" level="any"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Solution

  • Assuming you only have access to an XSLT 2 processor which doesn't support start-at (https://www.w3.org/TR/xslt20/#number) you can use

    <xsl:template match="M_856/G_HL/S_HL/D_734">
    <xsl:copy>
      <xsl:variable name="pos">
        <xsl:number count="M_856/G_HL/S_HL/D_734" level="any"/>
      </xsl:variable>
      <xsl:value-of select="$pos - 1"/>
    </xsl:copy>
    </xsl:template>