Jkoul
Jkoul

Reputation: 25

XSLT Increment reset upon change in element

XML:

<?xml version="1.0" encoding="utf-8"?>
  <Projects> 
    <Project GUID="K9"> 
    <Name>Range</Name>
    <WBSs>
        <WBS GUID="2">
            <Name>Site</Name>
            <ParentWBS/>
            <ProjectGUID>K9</ProjectGUID>
            <ObjectId>99040</ObjectId>
            <Activities/>
            <WBSs>
                <WBS GUID="1">
                <Name>West</Name>
                <ParentWBS>2</ParentWBS>
                <ProjectGUID>K9</ProjectGUID>
                <ObjectId>99046</ObjectId>
                <Activities>
                  <Activity GUID="A100">
                    <Name>Task</Name>
                    <ProjectGUID>K17</ProjectGUID>
                    <WBSCode>1</WBSCode>
                  </Activity>
                </Activities>
             </WBS>
             <WBS GUID="2">
                 <Name>South</Name>
                 <ParentWBS>2</ParentWBS>
                 <ProjectGUID>K9</ProjectGUID>
                 <ObjectId>99047</ObjectId>
                 <Activities>
                   <Activity GUID="A200">
                     <Name>Task 2</Name>
                   </Activity>
                 </Activities>
             </WBS>
             <WBS GUID="3">
                 <Name>North</Name>
                 <ParentWBS>2</ParentWBS>
                 <ProjectGUID>K9</ProjectGUID>
                 <ObjectId>99048</ObjectId>
                 <Activities/>
             </WBS>
          </WBSs>
      </WBS>
    </WBSs>
    <Activities/>
  </Project>
</Projects>

This is my current output:

<OBJECTID>99046</OBJECTID >
<ACTIVITY>0010</ACTIVITY>
<OBJECTID>99047</OBJECTID >
<ACTIVITY>0020</ACTIVITY>

Desired output:

<OBJECTID>99046</OBJECTID >
<ACTIVITY>0010</ACTIVITY>
<OBJECTID>99047</OBJECTID >
<ACTIVITY>0010</ACTIVITY>

When I have existing Activity and existing OBJECTID, the first 2 WHEN clauses work fine. The problem arises when there is no existing ObjectID or ObjectID changes in the 3rd WHEN. What I need is to start at ‘0010’ and increment by 10 until $ObjectID changes, then start at ‘0010’ again and so on. My background is procedural programming so still getting used to functional way of doing things and the restriction of not changing variables. Thanks in advance.

Here's the relevant XSLT code:

<ACTIVITY> 
<!-- count($ExistingActivity) = 1 -> ObjectId & Activity Id exist, increment $LastObjectIdActivity/ACTIVITY
   count($ExistingObjectId) = 1 -> ObjectId exists, increment $LastObjectId/ACTIVITY  
   count($ExistingObjectId) = 0 -> $ObjectId start at 0010 and keep incrementing until ObjectId change. 
-->
   <xsl:variable name="incr" select="10"/>
     <xsl:choose>
        <xsl:when test="count($ExistingActivity) = 1">      <!-- Exact match of ObjectId & Activity -->
        <!-- Get last existing ObjectId activity -->                        
          <xsl:variable name="temp" select="$LastObjectIdActivity/ACTIVITY"/>                                 
          <xsl:variable name="Oper" select="format-number($temp, '0000')"/>                              
          <xsl:value-of select="$Oper"/>
        </xsl:when>
        <xsl:when test="count($ExistingObjectId) = 1"> <!-- Activity not found, But ObjectId exists-->
        <!-- Get last existing ObjectId activity -->
          <xsl:variable name="temp" select="$LastObjectId/ACTIVITY + $incr"/>                                 
          <xsl:variable name="Oper" select="format-number($temp, '0000')"/>                              
          <xsl:value-of select="$Oper"/>
        </xsl:when>                                                                            
        <xsl:when test="count($ExistingObjectId) = 0">   <!-- No Existing ObjectId -->
          <xsl:variable name="pos" select="(position() * 10)"/>  
          <xsl:variable name="NextOper" select="format-number($pos, '0000')"/>  <!-- Start Activity at 0010 reset on new ObjectId-->
          <xsl:value-of select="$NextOper"/>
          <!-- $NextOper should be incremented by 10 -->                           
        </xsl:when> 
        <xsl:otherwise>
        </xsl:otherwise>                           
     </xsl:choose>                    
</ACTIVITY>

Upvotes: 1

Views: 338

Answers (1)

daniu
daniu

Reputation: 15008

I think what you want is to assign a value to each of the activities, so that's what you want to match

<xsl:template match="//Activity">
<OBJECTID>
    <xsl:value-of select="../../ObjectId" />
</OBJECTID>
<ACTIVITY>
    <xsl:value-of select="format-number(10 * (count(preceding-sibling::*) +1), '0000') "/>
</ACTIVITY>
</xsl:template>

That would give you the OBJECTID/ACTIVITY pair for every activity in the input. The count expression evaluates the number of preceding sibling activities, ie the 1-based index.

Upvotes: 1

Related Questions