Reputation: 5
I want to limit the innermost for-each loop (Loop_CLM/CLM) for its parent loop. For example, if innermost will loop more than 2 times, then break and start parent loop and inner from 4th position.
In output, each SUB segment must have max 2 CLM segment, if more then repeat SUB with remaining CLM segment.
I found somewhat similar post xslt - iterate nodes in chunks, but the parent loop has single occurrence.
Attaching the source XML, XSLT, actual output XML and desired output XML.
Modified Source XML:
<OB_X1>
<Pro>
<GivenProID>101</GivenProID>
<LoopSub>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10111</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10112</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10113</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10114</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10111</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10112</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10113</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10114</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1013</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10111</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10112</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1013</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10113</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10114</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
</LoopSub>
</Pro>
<Pro>
<GivenProID>102</GivenProID>
<LoopSub>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10111</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10112</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10113</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10114</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10115</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10116</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10111</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10112</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10113</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10114</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLM>
<CLMID>10115</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
<CLM>
<CLMID>10116</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</CLM>
</LoopCLM>
</LoopSub>
</Pro>
</OB_X1>
XSLT:
<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates select="/Loop_Pro" />
</xsl:template>
<xsl:template match="/Loop_Pro">
<OB_X1>
<xsl:for-each select="Pro">
<Pro>
<GivenProID>
<xsl:value-of select="ProID" />
</GivenProID>
<LoopSub>
<xsl:for-each select="Loop_Sub/Sub">
<GivenSubID>
<xsl:value-of select="SubID" />
</GivenSubID>
<LoopCLM>
<xsl:for-each select="Loop_CLM/CLM">
<CLMID>
<xsl:value-of select="CLMID" />
</CLMID>
</xsl:for-each>
</LoopCLM>
</xsl:for-each>
</LoopSub>
</Pro>
</xsl:for-each>
</OB_X1>
</xsl:template>
</xsl:stylesheet>
Output actual XML:
<OB_X1>
<Pro>
<GivenProID>101</GivenProID>
<LoopSub>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLMID>10111</CLMID>
<CLMID>10112</CLMID>
<CLMID>10113</CLMID>
<CLMID>10114</CLMID>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLMID>10111</CLMID>
<CLMID>10112</CLMID>
<CLMID>10113</CLMID>
<CLMID>10114</CLMID>
</LoopCLM>
<GivenSubID>1013</GivenSubID>
<LoopCLM>
<CLMID>10111</CLMID>
<CLMID>10112</CLMID>
<CLMID>10113</CLMID>
<CLMID>10114</CLMID>
</LoopCLM>
</LoopSub>
</Pro>
<Pro>
<GivenProID>102</GivenProID>
<LoopSub>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLMID>10111</CLMID>
<CLMID>10112</CLMID>
<CLMID>10113</CLMID>
<CLMID>10114</CLMID>
<CLMID>10115</CLMID>
<CLMID>10116</CLMID>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLMID>10111</CLMID>
<CLMID>10112</CLMID>
<CLMID>10113</CLMID>
<CLMID>10114</CLMID>
<CLMID>10115</CLMID>
<CLMID>10116</CLMID>
</LoopCLM>
</LoopSub>
</Pro>
</OB_X1>
Modified Desired Output XML:
<OB_X1>
<Pro>
<GivenProID>101</GivenProID>
<LoopSub>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLMID>10111</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
<CLMID>10112</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</LoopCLM>
<GivenSubID>1011</GivenSubID>
<LoopCLM>
<CLMID>10113</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
<CLMID>10114</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLMID>10111</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
<CLMID>10112</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</LoopCLM>
<GivenSubID>1012</GivenSubID>
<LoopCLM>
<CLMID>10113</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
<CLMID>10114</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</LoopCLM>
<GivenSubID>1013</GivenSubID>
<LoopCLM>
<CLMID>10111</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
<CLMID>10112</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</LoopCLM>
<GivenSubID>1013</GivenSubID>
<LoopCLM>
<CLMID>10113</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
<CLMID>10114</CLMID>
<nextfield1>new1</nextfield1>
<nextfield2>new2</nextfield2>
</LoopCLM>
</LoopSub>
</Pro>
Appreciate any help !
Thanks, Harish
Upvotes: 0
Views: 2282
Reputation: 117165
Wouldn't this be simpler (and more manageable)?
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:strip-space elements="*"/>
<xsl:variable name="group-size" select="2"/>
<xsl:template match="/Loop_Pro">
<OB_X1>
<xsl:apply-templates select="Pro"/>
</OB_X1>
</xsl:template>
<xsl:template match="Pro">
<xsl:copy>
<GivenProID>
<xsl:value-of select="ProID"/>
</GivenProID>
<xsl:apply-templates select="Loop_Sub"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Loop_Sub">
<LoopSub>
<xsl:apply-templates select="Sub"/>
</LoopSub>
</xsl:template>
<xsl:template match="Sub">
<xsl:variable name="subID" select="SubID"/>
<xsl:for-each select="Loop_CLM/CLM[position() mod $group-size = 1]">
<GivenSubID>
<xsl:value-of select="$subID"/>
</GivenSubID>
<LoopCLM>
<xsl:copy-of select="(. | following-sibling::CLM[position() < $group-size])/CLMID"/>
</LoopCLM>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Reputation: 5432
I hope this would do the job(the breakSize is variable, so you can have any value you want):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:strip-space elements="*"/>
<xsl:variable name="breakSize">2</xsl:variable>
<xsl:template match="/Loop_Pro">
<OB_X1>
<xsl:for-each select="Pro">
<xsl:copy>
<GivenProID>
<xsl:value-of select="ProID"/>
</GivenProID>
<xsl:for-each select="Loop_Sub">
<LoopSub>
<xsl:for-each select="Sub">
<xsl:call-template name="LoopCLM">
<xsl:with-param name="pos" select="1"/>
</xsl:call-template>
</xsl:for-each>
</LoopSub>
</xsl:for-each>
</xsl:copy>
</xsl:for-each>
</OB_X1>
</xsl:template>
<xsl:template name="LoopCLM">
<xsl:param name="pos"/>
<GivenSubID>
<xsl:value-of select="SubID"/>
</GivenSubID>
<LoopCLM>
<xsl:copy-of select="Loop_CLM/CLM[position() <= $pos + $breakSize - 1 and position() >= $pos]/CLMID"/>
</LoopCLM>
<xsl:if test="Loop_CLM/CLM[position() = $pos + $breakSize]">
<xsl:call-template name="LoopCLM">
<xsl:with-param name="pos" select="$pos + $breakSize"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1