在XSLT中限制内部for-each循环的迭代

时间:2015-02-11 00:25:45

标签: xml xslt

我想为其父循环限制最里面的for-each循环(Loop_CLM / CLM)。例如,如果innermost将循环超过2次,则中断并从第4个位置开始父循环和内部。

在输出中,每个SUB段必须具有最多2个CLM段,如果更多则重复SUB并保留剩余的CLM段。

我发现有些类似的帖子xslt - iterate nodes in chunks,但是父循环有一次出现。

附加源XML,XSLT,实际输出XML和所需的输出XML。

修改后的源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>

输出实际的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>

修改了所需的输出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>

感谢任何帮助!

谢谢, 哈里什

2 个答案:

答案 0 :(得分:1)

我希望这可以胜任(breakSize是可变的,所以你可以拥有你想要的任何值):

<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() &lt;= $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>

答案 1 :(得分:0)

这不会更简单(也更易于管理)吗?

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() &lt; $group-size])/CLMID"/>
        </LoopCLM>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>