Search code examples
xslt-2.0edixslt-3.0

XSLT - Adding a sequence number/counter to an element while copying all other elements


Dears, I have below xml its an edi xml having 2 documents inside. I would like to assign a sequence number for each ST and SE under M_810 I have 2 M_810 for my First M_810 - ST-D_329 and SE-D-329 - I want to have sequence number 2001 Second M_810 - ST-D_329 and SE-D_329 - I want to have sequence number 2002

I have tried below code . its always giving me the 2001 at the required places. Looking for some help on fixing this.

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>    
<xsl:template match="@*|node()">
<xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="D_329">
<xsl:if test="((../name() = 'S_ST') or (../name() = 'S_SE'))">
<D_329><xsl:value-of select="2000 + ../position()"/></D_329>    
</xsl:if>    
</xsl:template>
</xsl:stylesheet>

src xml:

        <?xml version='1.0' encoding='UTF-8'?><Interchange>
        <M_810>
                <S_ST>
                    <D_143>810</D_143>
                    <D_329>47857</D_329>
                </S_ST>
                <S_BIG>
                    <D_373>20210128</D_373>
                    <D_76>917183</D_76>
                    <D_373_2>20210120</D_373_2>
                    <D_324>13453796</D_324>
                </S_BIG>
                <S_SE>
                    <D_96>21</D_96>
                    <D_329>47857</D_329>
                </S_SE>
            </M_810>                
            <M_810>
                <S_ST>
                    <D_143>810</D_143>
                    <D_329>47858</D_329>
                </S_ST>
                <S_BIG>
                    <D_373>20210128</D_373>
                    <D_76>917184</D_76>
                    <D_373_2>20210120</D_373_2>
                    <D_324>13453797</D_324>
                </S_BIG>
                <S_SE>
                    <D_96>21</D_96>
                    <D_329>47858</D_329>
                </S_SE>
            </M_810>
        </Interchange>

Required output:

        <?xml version="1.0" encoding="UTF-8"?><Interchange>
        <M_810>
                <S_ST>
                    <D_143>810</D_143>
                    <D_329>2001</D_329>
                </S_ST>
                <S_BIG>
                    <D_373>20210128</D_373>
                    <D_76>917183</D_76>
                    <D_373_2>20210120</D_373_2>
                    <D_324>13453796</D_324>
                </S_BIG>
                <S_SE>
                    <D_96>21</D_96>
                    <D_329>2001</D_329>
                </S_SE>
            </M_810>                
            <M_810>
                <S_ST>
                    <D_143>810</D_143>
                    <D_329>2002</D_329>
                </S_ST>
                <S_BIG>
                    <D_373>20210128</D_373>
                    <D_76>917184</D_76>
                    <D_373_2>20210120</D_373_2>
                    <D_324>13453797</D_324>
                </S_BIG>
                <S_SE>
                    <D_96>21</D_96>
                    <D_329>2002</D_329>
                </S_SE>
            </M_810>
         </Interchange>

xml nodes to be modified for each occurrence in the parent:

  <S_ST>
    <D_143>810</D_143> 
    <D_329>47857</D_329> >> <D_329>2001</D_329>
</S_ST>
and 
    <S_SE>
      <D_96>21</D_96>
      <D_329>47857</D_329> >> <D_329>2001</D_329>
    </S_SE>

Solution

  • Assuming XSLT 3, it sounds as if you want

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="#all"
        version="3.0">
    
      <xsl:mode on-no-match="shallow-copy"/>
    
      <xsl:template match="M_810/S_ST/D_329">
          <xsl:copy>
              <xsl:number count="M_810/S_ST/D_329" start-at="2001" level="any"/>
          </xsl:copy>
      </xsl:template>
      
      <xsl:template match="M_810/S_SE/D_329">
          <xsl:copy>
              <xsl:number count="M_810/S_SE/D_329" start-at="2001" level="any"/>
          </xsl:copy>
      </xsl:template>
      
    </xsl:stylesheet>
    

    I haven't quite been able to check the right output, check yourself or if it doesn't work consider to cut irrelevant elements from the samples to ease our task to see the elements you want to transform and number.