Xml XSLT以偶数分布对相邻值进行分组

Xml XSLT以偶数分布对相邻值进行分组,xml,xslt,Xml,Xslt,我希望将相邻的值均匀地分布到一组中,使每组的总数大于300但小于390。为了实现这一点,我意识到有时需要拆分这些值,以达到设定的组数 如果我从下面开始,我只需要5秒: <root> <entry>5</entry> <entry>90</entry> <entry>55</entry> <entry>145</entry> <entry>

我希望将相邻的值均匀地分布到一组中,使每组的总数大于300但小于390。为了实现这一点,我意识到有时需要拆分这些值,以达到设定的组数

如果我从下面开始,我只需要5秒:

<root>
    <entry>5</entry>
    <entry>90</entry>
    <entry>55</entry>
    <entry>145</entry>
    <entry>90</entry>
    <entry>105</entry>
    <entry>270</entry>
    <entry>150</entry>
    <entry>145</entry>
    <entry>135</entry>
    <entry>140</entry>
    <entry>145</entry>
    <entry>155</entry>
    <entry>130</entry>
    <entry>125</entry>
</root>`

5.
90
55
145
90
105
270
150
145
135
140
145
155
130
125
`
我想以这样的方式结束:

<root>
  <group total="380">
    <entry>5</entry>
    <entry>90</entry>
    <entry>55</entry>
    <entry>145</entry>
    <entry>90</entry>
  </group>
  <group total="375">
    <entry>105</entry>
    <entry>270</entry>
  </group>
  <group total="390">
    <entry>150</entry>
    <entry>145</entry>
    <entry split='yes'>105</split>
  </group>
  <group total="390">
    <entry split='yes'>30</entry>
    <entry>140</entry>
    <entry>145</entry>
    <entry split='yes'>75</entry>
  </group>
  <group total="335">
    <entry split='yes'>80</entry>
    <entry>130</entry>
    <entry>125</entry>
  </group>
</root>
<xsl:variable name="total" select="sum(//entry)">

<xsl:variable name="set-number" select="xs:integer(ceiling($total div 390))"/>

<xsl:variable name="count" select="floor($total) div $set-number)"/>

<xsl:for-each-group select="entry" group-ending-with="*[(position() mod $count) = 0]">
   <group total="{sum(current-group())}">
      <xsl:apply-templates select="current-group()"/>
   </group>
</xsl:for-each-group>


5.
90
55
145
90
105
270
150
145
105
30
140
145
75
80
130
125
我得到的最接近的结果是这样的:

<root>
  <group total="380">
    <entry>5</entry>
    <entry>90</entry>
    <entry>55</entry>
    <entry>145</entry>
    <entry>90</entry>
  </group>
  <group total="375">
    <entry>105</entry>
    <entry>270</entry>
  </group>
  <group total="390">
    <entry>150</entry>
    <entry>145</entry>
    <entry split='yes'>105</split>
  </group>
  <group total="390">
    <entry split='yes'>30</entry>
    <entry>140</entry>
    <entry>145</entry>
    <entry split='yes'>75</entry>
  </group>
  <group total="335">
    <entry split='yes'>80</entry>
    <entry>130</entry>
    <entry>125</entry>
  </group>
</root>
<xsl:variable name="total" select="sum(//entry)">

<xsl:variable name="set-number" select="xs:integer(ceiling($total div 390))"/>

<xsl:variable name="count" select="floor($total) div $set-number)"/>

<xsl:for-each-group select="entry" group-ending-with="*[(position() mod $count) = 0]">
   <group total="{sum(current-group())}">
      <xsl:apply-templates select="current-group()"/>
   </group>
</xsl:for-each-group>


这给了我:

<root>  
    <group total="150">
        <entry>5</entry>
        <entry>90</entry>
        <entry>55</entry>
    </group>
    <group total="340">
        <entry>145</entry>
        <entry>90</entry>
        <entry>105</entry>
    </group>
    <group total="565">
        <entry>270</entry>
        <entry>150</entry>
        <entry>145</entry>
    </group>
    <group total="420">
        <entry>135</entry>
        <entry>140</entry>
        <entry>145</entry>
    </group>
    <group total="410">
        <entry>155</entry>
        <entry>130</entry>
        <entry>125</entry>
    </group>
</root>

5.
90
55
145
90
105
270
150
145
135
140
145
155
130
125

这给了我正确的组数,但不是很均匀的分布

这可能是XSLT 3.0的工作
xsl:iterate
,尽管即使这样,我也很难一步处理、汇总和拆分输入数据

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

  <xsl:param name="min" as="xs:integer" select="300"/>
  <xsl:param name="max" as="xs:integer" select="390"/>

  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="root">
      <xsl:copy>
          <xsl:iterate select="entry">
              <xsl:param name="total" as="xs:integer" select="0"/>
              <xsl:param name="group" as="element(entry)*" select="()"/>
              <xsl:on-completion>
                  <xsl:if test="$group">
                      <group>
                          <xsl:copy-of select="$group"/>
                      </group>
                  </xsl:if>
              </xsl:on-completion>
              <xsl:variable name="value" select="xs:integer(.)"/>
              <xsl:variable name="sum" as="xs:integer" select="$total + $value"/>
              <xsl:variable name="split" select="$sum gt $max and $total lt $min"/>
              <xsl:variable name="splitted-values" as="element(entry)*">
                  <entry split="true">{$max - $total}</entry>
                  <entry split="true">{$sum - $max}</entry>
              </xsl:variable>
              <xsl:if test="$sum gt $max">
                  <group total="{$total + (if ($split) then $splitted-values[1][$split] else 0)}">
                      <xsl:copy-of select="$group, $splitted-values[1][$split]"/>
                  </group>
              </xsl:if>
              <xsl:next-iteration>
                  <xsl:with-param name="total" select="if ($sum > $max) then (if ($split) then $splitted-values[2] else xs:integer(.)) else $sum"/>
                  <xsl:with-param name="group"
                    select="if ($split and $sum gt $max)
                            then $splitted-values[2]
                            else if ($sum gt $max)
                            then .
                            else ($group, .)"/>
              </xsl:next-iteration>
          </xsl:iterate>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

这很有魅力。是的,我的计算失败了(部分原因是我想让电脑代替我做这件事)。非常感谢您——我还没有对XSLT3.0进行过很多探索,但我肯定会在将来对它进行更多的研究!