Asorium
Asorium

Reputation: 13

Counting up an index for empty values and more in XSLT

I'm trying to solve this problem and searching the internet for several days now but have no clue how to do it right.. Maybe someone here can give me a hint or tell me if it is even possible to solve with XSLT 1.0.

Problem

I need an XSL transformation (XSLT 1.0) to be completed with the following things:

Filling the empty values of „CALLOUT“:

Filling the field "YCSPOSNO_PI":

Filling the field „EXPLA“:

--> Example for EXPLA: LEVEL_NO CALLOUT EXPLA 1 17.1 17.1 = 17.2 + 21 2 17.2 17.2 = 17 + 18 + 19 + 20 3 17 3 18 3 19 3 20 2 21

EXPLA for 17.1 = "17.1 = 17.2 + 21" (because always LEVEL_NO + 1 of actual LEVEL_NO belong to the actual LEVEL_ONE; 17.1 has LEVEL_NO "1" so all LEVEL_NO "2" below until the LEVEL_NO changes to "1" the next time belong to this one)

EXPLA for 17.2 = "17.2 = 17 + 18 + 19 + 20" (17.2 has LEVEL_NO "2", so all LEVEL_NO "3" until the next occurance of LEVEL_NO "1" belong to this one)

Source

<?xml version="1.0" encoding="utf-8"?>
<ns:MT_FlatFile_Lists_Cu xmlns:ns="urn:las:pp:ss1:tar">
<Cu_Records>
    <Record>
        <ESN>123</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>1</LEVEL_NO>
        <CALLOUT></CALLOUT>
    </Record>
    <Record>
        <ESN>123</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>2</LEVEL_NO>
        <CALLOUT></CALLOUT>
    </Record>
    <Record>
        <ESN>123</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>3</LEVEL_NO>
        <CALLOUT>3</CALLOUT>
    </Record>
    <Record>
        <ESN>123</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>3</LEVEL_NO>
        <CALLOUT>4</CALLOUT>
    </Record>
    <Record>
        <ESN>123</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>2</LEVEL_NO>
        <CALLOUT>5</CALLOUT>
    </Record>
    <Record>
        <ESN>456</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>1</LEVEL_NO>
        <CALLOUT></CALLOUT>
    </Record>
    <Record>
        <ESN>456</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>1</LEVEL_NO>
        <CALLOUT></CALLOUT>
    </Record>
    <Record>
        <ESN>456</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>2</LEVEL_NO>
        <CALLOUT>17</CALLOUT>
    </Record>
    <Record>
        <ESN>456</ESN>
        <GRAPHIC_NAME>2.png</GRAPHIC_NAME>
        <LEVEL_NO>2</LEVEL_NO>
        <CALLOUT>18</CALLOUT>
    </Record>
</Cu_Records>
</ns:MT_FlatFile_Lists_Cu>

Desired Output

<?xml version='1.0' ?>
<YCSMST01>
  <IDOC BEGIN="1">
    <EDI_DC40 SEGMENT="1">
      <SNDPOR/>
      <SNDPRT/>
      <SNDPRN/>
      <SNDLAD/>
    </EDI_DC40>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>123#1</YCSSTKLID>
      <CALLOUT>3.1</CALLOUT>
      <YCSPOSNO_PI>3A</YCSPOSNO_PI>
      <EXPLA>3.1 = 3.2+5</EXPLA>
    </YCSMOTOR_STKL01>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>123#1</YCSSTKLID>
      <CALLOUT>3.2</CALLOUT>
      <YCSPOSNO_PI>3B</YCSPOSNO_PI>
      <EXPLA>3.2 = 4+5</EXPLA>
    </YCSMOTOR_STKL01>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>123#2</YCSSTKLID>
      <CALLOUT>3</CALLOUT>
      <YCSPOSNO_PI>3C</YCSPOSNO_PI>
      <EXPLA/>
    </YCSMOTOR_STKL01>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>123#2</YCSSTKLID>
      <CALLOUT>4</CALLOUT>
      <YCSPOSNO_PI>4A</YCSPOSNO_PI>
      <EXPLA/>
    </YCSMOTOR_STKL01>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>123#2</YCSSTKLID>
      <CALLOUT>5</CALLOUT>
      <YCSPOSNO_PI>5A</YCSPOSNO_PI>
      <EXPLA/>
    </YCSMOTOR_STKL01>
  </IDOC>
</YCSMST01>
<YCSMST01>
  <IDOC BEGIN="1">
    <EDI_DC40 SEGMENT="1">
      <SNDPOR/>
      <SNDPRT/>
      <SNDPRN/>
      <SNDLAD/>
    </EDI_DC40>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>456#2</YCSSTKLID>
      <CALLOUT>17.1</CALLOUT>
      <YCSPOSNO_PI>17A</YCSPOSNO_PI>
      <EXPLA>17.1 = 17+18</EXPLA>
    </YCSMOTOR_STKL01>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>456#2</YCSSTKLID>
      <CALLOUT>17.2</CALLOUT>
      <YCSPOSNO_PI>17B</YCSPOSNO_PI>
      <EXPLA>17.2 = 17+18</EXPLA>
    </YCSMOTOR_STKL01>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>456#2</YCSSTKLID>
      <CALLOUT>17</CALLOUT>
      <YCSPOSNO_PI>17C</YCSPOSNO_PI>
      <EXPLA/>
    </YCSMOTOR_STKL01>
    <YCSMOTOR_STKL01 SEGMENT="1">
      <YCSSTKLID>456#2</YCSSTKLID>
      <CALLOUT>18</CALLOUT>
      <YCSPOSNO_PI>18A</YCSPOSNO_PI>
      <EXPLA/>
    </YCSMOTOR_STKL01>
  </IDOC>
</YCSMST01>

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" xmlns:xsltc="http://xml.apache.org/xalan/xsltc" xmlns:map="java.util.Map" xmlns:dyn="com.sap.aii.mapping.api.DynamicConfiguration" xmlns:key="com.sap.aii.mapping.api.DynamicConfigurationKey" xmlns:ns="urn:las:pp:ss1:tar" exclude-result-prefixes="xs ns xsl map key dyn xsltc">
    <xsl:output indent="yes"/>
    <xsl:key name="a" match="Record" use="ESN"/>
    <xsl:key name="b" match="Record" use="concat(ESN, '#', GRAPHIC_NAME)"/>
    <xsl:template match="/">
        <xsl:apply-templates select="ns:MT_FlatFile_Lists_Cu/Cu_Records/Record[generate-id(.) = generate-id(key('b', concat(ESN, '#', GRAPHIC_NAME)))]" mode="head"/>
    </xsl:template>
    <xsl:template match="Record" mode="head">
    <xsl:variable name="stueckliste" select="concat(ESN, '#', GRAPHIC_NAME)"/>
        <YCSMST01>
            <IDOC BEGIN="1">
                <EDI_DC40 SEGMENT="1">
                    <SNDPOR/>
                    <SNDPRT/>
                    <SNDPRN/>
                    <SNDLAD/>
                </EDI_DC40>
                <xsl:apply-templates select="/ns:MT_FlatFile_Lists_Cu/Cu_Records/Record[concat(ESN, '#', GRAPHIC_NAME) = $stueckliste]" mode="pos"/>
            </IDOC> 
        </YCSMST01> 
    </xsl:template>
                
                
    <xsl:template match="Record" mode="pos">                
                
                <!-- Segment YCSMOTOR_STKL01 -->
                <YCSMOTOR_STKL01 SEGMENT="1">
                    <YCSSTKLID>
                        <xsl:value-of select="concat(ESN,'#',substring-before(GRAPHIC_NAME, '.'))"/>
                    </YCSSTKLID>
                    <!-- Fill Callout into <CALLOUT> -->
                    <xsl:variable name="callout" select="CALLOUT"/>
                    <xsl:choose>
                        <!-- Take value of CALLOUT if CALLOUT has a value -->
                        <xsl:when test="$callout and (not($callout = ''))">
                            <CALLOUT>
                                <xsl:value-of select="$callout"/>
                            </CALLOUT>
                        </xsl:when>
                        <xsl:otherwise>
                            <!-- Apply-templates to get next filled Callout value -->
                            <xsl:apply-templates select="following-sibling::Record[CALLOUT != ''][1]" mode="nextCallout"/>
                        </xsl:otherwise>
                    </xsl:choose>
                    <YCSPOSNO_PI></YCSPOSNO_PI>
                    <EXPLA></EXPLA>
                </YCSMOTOR_STKL01>
    </xsl:template>
    <!-- Template to get next filled CALLOUT -->
    <xsl:template match="Record" mode="nextCallout">
        <xsl:variable name="nextCallout" select="CALLOUT"/>
        <CALLOUT>
            <xsl:value-of select="$nextCallout"/>
        </CALLOUT>
    </xsl:template>
</xsl:stylesheet>

Thanks in advance.

Upvotes: 1

Views: 90

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117073

Consider the following minimized stylesheet:

XSLT 1.0

<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:key name="pre" match="Record[CALLOUT='']" use="generate-id(following-sibling::Record[CALLOUT!=''][1])" />

<xsl:template match="/*">
    <output>
        <xsl:for-each select="Cu_Records/Record[CALLOUT!='']">
            <xsl:variable name="preceding" select="key('pre', generate-id())" />
            <xsl:variable name="callout" select="CALLOUT" />
            <!-- process preceding siblings -->
            <xsl:for-each select="$preceding">
                <item>
                    <callout>
                        <xsl:value-of select="$callout"/>
                        <xsl:text>.</xsl:text>
                        <xsl:value-of select="position()"/>
                    </callout>
                    <posno>
                        <xsl:value-of select="$callout"/>
                        <xsl:number value="position()" format="A"/>
                    </posno>
                </item>
            </xsl:for-each>
            <!-- add the current record -->
            <item>
                <callout>
                    <xsl:value-of select="$callout"/>
                </callout>
                <posno>
                    <xsl:value-of select="$callout"/>
                    <xsl:number value="count($preceding)+1" format="A"/>
                </posno>
            </item>
        </xsl:for-each>
    </output>       
</xsl:template>

</xsl:stylesheet>

Applied to your input example, this will return:

Result

<?xml version="1.0" encoding="UTF-8"?>
<output>
  <item>
    <callout>3.1</callout>
    <posno>3A</posno>
  </item>
  <item>
    <callout>3.2</callout>
    <posno>3B</posno>
  </item>
  <item>
    <callout>3</callout>
    <posno>3C</posno>
  </item>
  <item>
    <callout>4</callout>
    <posno>4A</posno>
  </item>
  <item>
    <callout>5</callout>
    <posno>5A</posno>
  </item>
  <item>
    <callout>17.1</callout>
    <posno>17A</posno>
  </item>
  <item>
    <callout>17.2</callout>
    <posno>17B</posno>
  </item>
  <item>
    <callout>17</callout>
    <posno>17C</posno>
  </item>
  <item>
    <callout>18</callout>
    <posno>18A</posno>
  </item>
</output>

This should answer your first two questions (which is one more than it should). Please ask your third question separately (I couldn't understand it anyway).


Note that this assumes that the last Record does not have an empty CALLOUT.

Upvotes: 1

Related Questions