xslt-1.0soajdeveloper-11g

jdeveloper XSLT for each loop at multiple entities break


Input XML :

<Response>
         <Quote qtID="5443655">
             <Incidents>
               <Incident name="Subway1" active="true" primary="false" ActivityID="32">
                  <IncidentConfig>
                     <AccountID>CCCCCCCC</AccountID>
                  </IncidentConfig>
                  <cals>
                     <cal name="PMP" value="32.0">
                   </cal>
                     <cal name="TC" value="85.83612">
                     </cal>
                     <cal name="D" value="70.83612">
                        </cal>
                    </cals>
               </Incident>
               <Incident name="Subway2" active="true" primary="true" ActivityID="33">
                  <IncidentConfig>
                     <AccountID>DDDDD</AccountID>
                  </IncidentConfig>
                  <cals>
                     <cal name="TC" value="26.0">
                        </cal>
                     <cal name="D" value="86.83612">
                        </cal>
                    </cals>
               </Incident>
                <Incident name="Subway3" active="true" primary="false" ActivityID="33">
                  <IncidentConfig>
                     <AccountID>DDDDD</AccountID>
                  </IncidentConfig>
                  <cals>
                     <cal name="PMP" value="39.0">
                        </cal>
                     <cal name="D" value="24.83612">
                        </cal>
                    </cals>
               </Incident>
            </Incidents>
         </Quote>
      </Response>

I know break is not possible in XSLT for-each loop. But from following example, If I want to show 'cal' element with name PMP exist then take PMP value if not, take TC value. I tried the below code but, didn't work.

<charge>
  <xsl:value-of select='/Response/Quote/Incidents/Incident/cals/cal[@name = "PMP"]'/> 
</charge>

Expected XML:

  <Incident>
      <charge>32.0</charge>
      </Incident>
       <Incident>
      <charge>26.0</charge>
      </Incident>
       <Incident>
      <charge>39.0</charge>
      </Incident>

Any help is appreciated.


Solution

  • I want to show 'cal' element with name PMP exist then take PMP value if not, take TC value.

    To take that literally, you would do:

    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:template match="/Response">
        <root>
            <xsl:for-each select="Quote/Incidents/Incident">
                <Incident>
                    <charge>
                        <xsl:variable name="pmp" select="cals/cal[@name='PMP']" />
                        <xsl:choose>
                            <xsl:when test="$pmp">
                                <xsl:value-of select="$pmp/@value"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="cals/cal[@name='TC']/@value"/>
                            </xsl:otherwise>
                        </xsl:choose>
                    </charge>
                </Incident>
            </xsl:for-each>
        </root>
    </xsl:template>
    
    </xsl:stylesheet>
    

    But if (as in your example) only one of those elements will be present, you could simplify the code to:

    <xsl:template match="/Response">
        <root>
            <xsl:for-each select="Quote/Incidents/Incident">
                <Incident>
                    <charge>
                        <xsl:value-of select="cals/cal[@name='PMP']/@value | cals/cal[@name='TC']/@value"/>
                    </charge>
                </Incident>
            </xsl:for-each>
        </root>
    </xsl:template>
    

    Likewise, if both can be present, but PMP will always come before TC, you could do:

    <xsl:value-of select="(cals/cal[@name='PMP'] | cals/cal[@name='TC'])[1]/@value"/>