XSL add a wrapper every time sum equals 12

前端 未结 3 365
一整个雨季
一整个雨季 2021-01-27 16:20

I want to turn this


  
  
  
          


        
相关标签:
3条回答
  • 2021-01-27 16:54

    Here a slightly shorter XSLT 1.0 version using following-sibling and an empty notest as default stack value ( <xsl:param name="items" select="/@empty-node-set" /> ).
    But basically same as michael.hor257k solution.

    <xsl:template match="/root">
        <xsl:copy>
            <xsl:apply-templates select="item[1]" />
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="item">
        <xsl:param name="items" select="/@empty-node-set" />
        <xsl:variable name="stack" select="$items | ." />
        <xsl:choose>
            <xsl:when test="sum($stack/@columns) >= 12 or not(following-sibling::item)"  >
                <row>
                    <xsl:copy-of select="$stack"/>
                </row>
                <xsl:apply-templates select="following-sibling::item[1]" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="following-sibling::item[1]">
                    <xsl:with-param name="items" select="$stack"/>
                </xsl:apply-templates>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    

    Using /@empty-node-set as empty stack was from Best practice regarding empty node-set initialization:

    ... the expression "/@empty-node-set" which is guaranteed (for XML 1.0) to be empty because the root node can never have attribute nodes.

    0 讨论(0)
  • 2021-01-27 16:56

    Here's an XSLT 2.0 solution:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="root">
        <xsl:copy>
          <!--
          Group <item> elements, ending each group when the sum of the @columns
          attribute of the current <item> element and the <item> elements that
          precede it is divisible by 12.
          -->
          <xsl:for-each-group select="item" group-ending-with="
            *[sum((
                number(@columns),
                for $c in preceding-sibling::item/@columns return number($c)
              )) mod 12 eq 0]
          ">
            <row>
              <xsl:apply-templates select="current-group()"/>
            </row>
          </xsl:for-each-group>
        </xsl:copy>
      </xsl:template>
    
      <!-- Identity template -->
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2021-01-27 17:02

    Here's one way you could look at it:

    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="/root">
        <xsl:copy>
            <xsl:call-template name="aggregate">
                <xsl:with-param name="items" select="item"/>
            </xsl:call-template>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template name="aggregate">
        <xsl:param name="items" select="/.."/>
        <xsl:param name="i" select="1"/>
        <xsl:variable name="stack-items" select="$items[position() &lt;= $i]" />
        <xsl:choose>
            <xsl:when test="sum($stack-items/@columns) >= 12 or $i >= count($items)">
                <row>
                    <xsl:copy-of select="$stack-items"/>
                </row>
                <xsl:if test="$i &lt; count($items)">
                    <xsl:call-template name="aggregate">
                        <xsl:with-param name="items" select="$items[position() > $i]"/>
                    </xsl:call-template>
                </xsl:if>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="aggregate">
                    <xsl:with-param name="items" select="$items"/>
                    <xsl:with-param name="i" select="$i + 1"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Do a search for sibling recursion for an alternative method.

    0 讨论(0)
提交回复
热议问题