Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xslt 将条目合并到页码_Xslt_Xslt 2.0 - Fatal编程技术网

Xslt 将条目合并到页码

Xslt 将条目合并到页码,xslt,xslt-2.0,Xslt,Xslt 2.0,我有如下索引条目: <entry name="a" page="1" /> <entry name="b" page="3" /> <entry name="b" page="4" /> <entry name="b" page="6" /> <entry name="c" page="7" /> 现在我想买点像 <index name="a" pages="1 /> <index name="b" pages=

我有如下索引条目:

<entry name="a" page="1" />
<entry name="b" page="3" />
<entry name="b" page="4" />
<entry name="b" page="6" />
<entry name="c" page="7" />

现在我想买点像

<index name="a" pages="1 />
<index name="b" pages="3-4, 6" />
<index name="c" pages="7" />

然后把“346”变成“346”。第一步很简单:

<xsl:for-each-group select="index" group-adjacent="@name">
  <xsl:element name="index">
    <xsl:attribute name="name" select="@name"/>
    <xsl:attribute name="pages" select="current-group()/@page"/>
  </xsl:element>
</xsl:for-each-group>

(当然,此处的“页面”属性可能有所不同)

现在是困难的一步,我应该如何迭代列表?必须有一些聪明的解决方案来检查下一个同级/@页面(我可以将页面按顺序排列)是否是当前的@page+1。

以下是一个示例:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  version="2.0">

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:template match="entries">
    <xsl:for-each-group select="entry" group-by="@name">
      <index name="{current-grouping-key()}">
        <xsl:attribute name="pages">
          <xsl:for-each-group select="current-group()/xs:integer(@page)" group-by="position() - .">
            <xsl:if test="position() gt 1">
              <xsl:text>, </xsl:text>
            </xsl:if>
            <xsl:value-of select="if (current-group()[2]) 
                                  then (current-group()[1], current-group()[last()])
                                  else ." 
                          separator="-"/>
          </xsl:for-each-group>
        </xsl:attribute>
      </index>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

, 
输入为

<entries>
<entry name="a" page="1" />
<entry name="b" page="3" />
<entry name="b" page="4" />
<entry name="b" page="6" />
<entry name="c" page="7" />
</entries>

我得到了结果

<index name="a" pages="1"/>
<index name="b" pages="3-4, 6"/>
<index name="c" pages="7"/>

这里是另一个解决方案

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs"      >
      <xsl:output omit-xml-declaration="yes" indent="yes"/>

      <xsl:template match="entries">
        <xsl:for-each-group select="entry" group-by="@name">
          <index name="{current-grouping-key()}">
            <xsl:attribute name="pages">
              <xsl:variable name="vAtribVals" as="xs:integer*">
                <xsl:perform-sort select="current-group()/@page/xs:integer(.)">
                  <xsl:sort data-type="number"/>
                </xsl:perform-sort>
              </xsl:variable>

              <xsl:sequence select=
                "$vAtribVals[1],
                 for $k in 2 to count($vAtribVals)
                   return
                     if($vAtribVals[$k] - $vAtribVals[$k -1] ne 1)
                       then concat(',', $vAtribVals[$k])
                       else
                         if($vAtribVals[$k+1] - $vAtribVals[$k] ne 1)
                           then concat('-', $vAtribVals[$k])
                           else()
                 "/>
            </xsl:attribute>
          </index>
        </xsl:for-each-group>
      </xsl:template>
</xsl:stylesheet>
<entries>
    <entry name="a" page="1" />
    <entry name="b" page="3" />
    <entry name="b" page="4" />
    <entry name="b" page="6" />
    <entry name="c" page="7" />
</entries>
<index name="a" pages="1"/>
<index name="b" pages="3-4,6"/>
<index name="c" pages="7"/>

当此转换应用于以下XML文档时

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs"      >
      <xsl:output omit-xml-declaration="yes" indent="yes"/>

      <xsl:template match="entries">
        <xsl:for-each-group select="entry" group-by="@name">
          <index name="{current-grouping-key()}">
            <xsl:attribute name="pages">
              <xsl:variable name="vAtribVals" as="xs:integer*">
                <xsl:perform-sort select="current-group()/@page/xs:integer(.)">
                  <xsl:sort data-type="number"/>
                </xsl:perform-sort>
              </xsl:variable>

              <xsl:sequence select=
                "$vAtribVals[1],
                 for $k in 2 to count($vAtribVals)
                   return
                     if($vAtribVals[$k] - $vAtribVals[$k -1] ne 1)
                       then concat(',', $vAtribVals[$k])
                       else
                         if($vAtribVals[$k+1] - $vAtribVals[$k] ne 1)
                           then concat('-', $vAtribVals[$k])
                           else()
                 "/>
            </xsl:attribute>
          </index>
        </xsl:for-each-group>
      </xsl:template>
</xsl:stylesheet>
<entries>
    <entry name="a" page="1" />
    <entry name="b" page="3" />
    <entry name="b" page="4" />
    <entry name="b" page="6" />
    <entry name="c" page="7" />
</entries>
<index name="a" pages="1"/>
<index name="b" pages="3-4,6"/>
<index name="c" pages="7"/>

生成所需的正确结果

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs"      >
      <xsl:output omit-xml-declaration="yes" indent="yes"/>

      <xsl:template match="entries">
        <xsl:for-each-group select="entry" group-by="@name">
          <index name="{current-grouping-key()}">
            <xsl:attribute name="pages">
              <xsl:variable name="vAtribVals" as="xs:integer*">
                <xsl:perform-sort select="current-group()/@page/xs:integer(.)">
                  <xsl:sort data-type="number"/>
                </xsl:perform-sort>
              </xsl:variable>

              <xsl:sequence select=
                "$vAtribVals[1],
                 for $k in 2 to count($vAtribVals)
                   return
                     if($vAtribVals[$k] - $vAtribVals[$k -1] ne 1)
                       then concat(',', $vAtribVals[$k])
                       else
                         if($vAtribVals[$k+1] - $vAtribVals[$k] ne 1)
                           then concat('-', $vAtribVals[$k])
                           else()
                 "/>
            </xsl:attribute>
          </index>
        </xsl:for-each-group>
      </xsl:template>
</xsl:stylesheet>
<entries>
    <entry name="a" page="1" />
    <entry name="b" page="3" />
    <entry name="b" page="4" />
    <entry name="b" page="6" />
    <entry name="c" page="7" />
</entries>
<index name="a" pages="1"/>
<index name="b" pages="3-4,6"/>
<index name="c" pages="7"/>

注意事项

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs"      >
      <xsl:output omit-xml-declaration="yes" indent="yes"/>

      <xsl:template match="entries">
        <xsl:for-each-group select="entry" group-by="@name">
          <index name="{current-grouping-key()}">
            <xsl:attribute name="pages">
              <xsl:variable name="vAtribVals" as="xs:integer*">
                <xsl:perform-sort select="current-group()/@page/xs:integer(.)">
                  <xsl:sort data-type="number"/>
                </xsl:perform-sort>
              </xsl:variable>

              <xsl:sequence select=
                "$vAtribVals[1],
                 for $k in 2 to count($vAtribVals)
                   return
                     if($vAtribVals[$k] - $vAtribVals[$k -1] ne 1)
                       then concat(',', $vAtribVals[$k])
                       else
                         if($vAtribVals[$k+1] - $vAtribVals[$k] ne 1)
                           then concat('-', $vAtribVals[$k])
                           else()
                 "/>
            </xsl:attribute>
          </index>
        </xsl:for-each-group>
      </xsl:template>
</xsl:stylesheet>
<entries>
    <entry name="a" page="1" />
    <entry name="b" page="3" />
    <entry name="b" page="4" />
    <entry name="b" page="6" />
    <entry name="c" page="7" />
</entries>
<index name="a" pages="1"/>
<index name="b" pages="3-4,6"/>
<index name="c" pages="7"/>
  • 页面
    属性在进一步处理之前进行排序,这样即使
    条目
    元素在源XML文档中没有按排序顺序出现,也可以进行正确的处理

  • 处理不依赖于整数值和位置之间的关系,这使得它适用于属性值不是整数的其他情况


  • 我可以请你帮我理解这一点吗?我不明白的第一件事是每个组的最内层
    循环中的
    groupby=“position()-.”
    position()
    指的是什么?最里面的环?而且
    来自外部组(没有意义)?
    是组中的第一个元素吗?-我应该用另一个问题来解释吗?group by的总体可以在
    select
    属性中找到,它是
    current-group()/xs:integer(@page)
    因此它是
    页面
    属性的整数值序列。序列中每个整数的
    groupby=“position()-1”
    计算
    position()
    减去该整数的表达式,这允许我们找到连续的整数序列,例如,组的总体为
    3,4,6
    groupby计算
    1-3=-2
    2-4=-2
    3-6=-3
    因此对于整数
    3
    4
    我们将它们分组。真令人印象深刻。我猜
    中的表达式是的,对,如果有多个项目,如果组中至少有第二个项目,那么我们输出
    firstItem-lastItem
    ,否则我们输出单个项目。