2

我有以下问题,我认为它有一个简单的解决方案,我只是没有知识。

例如,我有这个输入:

<set>
  <value>8</value>
  <value>1</value>
  <value>2</value>
  <value>10</value>
  <value>4</value>
  <value>22</value>
  <value>12</value>
  <value>45</value>
  <value>11</value>
  <value>3</value>
  <value>5</value>
  <value>9</value>
  <value>21</value>
  <value>6</value>
  <value>7</value>
  <value>13</value>
</set>

我想创建最多包含 10 个元素的序列,每个元素的数字是连续的且按升序排列。

期望的输出:

<MOrd>
  <range>
    <value>1</value>
    <value>2</value>
    <value>3</value>
    <value>4</value>
    <value>5</value>
    <value>6</value>
    <value>7</value>
    <value>8</value>
    <value>9</value>
    <value>10</value>
  </range>
  <range>
    <value>11</value>
    <value>12</value>
    <value>13</value>
  </range> 
  <range>
    <value>21</value>
    <value>22</value>
  </range>
  <range>
    <value>45</value>
  </range>
</Mord> 

到目前为止我有这段代码,但不知道如何继续:

<MOrd>
  <xsl:for-each select="$Set">
    <xsl:sort select="value" order="ascending" data-type="number"/>
    <xsl:for-each-group select="value" group-by"value">
      <range>
        <xsl:if test=".">
          <value>
            <xsl:value-of select="."/>
          </value>
        </xsl:if>
      </range>
    </xsl:for-each-group>
  </xsl:for-each>
</MOrd>

你会怎么从这里走?

4

2 回答 2

3

我认为您只需要通过一个简单的数学表达式对元素进行分组,即可确定 10 除以数字的次数

<xsl:for-each-group select="value" group-by="floor((number(.) - 1) div 10)">

试试这个 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="set">
    <MOrd>
      <xsl:for-each-group select="value" group-by="floor((number(.) - 1) div 10)">
          <xsl:sort select="." order="ascending" data-type="number"/>
          <range>
               <xsl:for-each select="current-group()">
                     <xsl:sort select="." order="ascending" data-type="number"/>
                     <xsl:copy-of select="." />
               </xsl:for-each>
           </range>
     </xsl:for-each-group>
    </MOrd>
  </xsl:template>
</xsl:stylesheet>

当应用于您的输入 XML 时,将输出以下内容

<MOrd>
   <range>
      <value>1</value>
      <value>2</value>
      <value>3</value>
      <value>4</value>
      <value>5</value>
      <value>6</value>
      <value>7</value>
      <value>8</value>
      <value>9</value>
      <value>10</value>
   </range>
   <range>
      <value>11</value>
      <value>12</value>
      <value>13</value>
   </range>
   <range>
      <value>21</value>
      <value>22</value>
   </range>
   <range>
      <value>45</value>
   </range>
</MOrd>
于 2013-08-28T22:41:41.733 回答
1

我知道这是一个老问题,但似乎手头的问题,对连续数字进行分组,并没有(完全)回答。您可以group-starting-with在 XSLT 2.0 中按如下方式执行此操作(在对输入进行排序之后):

<xsl:for-each-group select="value" 
    group-starting-with="value[xs:integer(preceding-sibling::value[1]) + 1 != xs:integer(.)]">
    <range>
        <xsl:copy-of select="current-group()"/>
    </range>
</xsl:for-each-group>

该方法之所以有效,是因为每次上一个兄弟节点不比当前节点低一个时,它都会触发一个新组。如果您的输入是,1,2,3,6,7,8,12,16,17它将被分组为1,2,36,7,8和。1216,17

该解决方案适用于 XSLT 2.0 和 3.0,但不适用于 XSLT 1.0。

于 2015-05-17T15:51:57.990 回答