XSLT分组

时间:2009-02-03 14:24:46

标签: xslt

我有一个简单的XML,有两个级别(Header和Line)标签,例如:

<?xml version="1.0"?>
<Header>
    <line>Line 1</line>
    <line>Line 2</line>
    <line>Line 3</line>
    <line>Line 4</line>
    <line>Line 5</line>
    <line>Line 6</line>
    <line>Line 7</line>
    <line>Line 8</line>
    <line>Line 9</line>
</Header>

我需要在X组(例如X = 3)线上对线进行分组,以便我的输出如下:

<?xml version="1.0"?>
<Header>
    <set>
        <line>Line 1</line>
        <line>Line 2</line>
        <line>Line 3</line>
    </set>
    <set>
        <line>Line 4</line>
        <line>Line 5</line>
        <line>Line 6</line>
    </set>
    <set>
        <line>Line 7</line>
        <line>Line 8</line>
        <line>Line 9</line>
    </set>
</Header> 

如何编写可以进行此类转换的XSLT?

谢谢!

0

4 个答案:

答案 0 :(得分:4)

以下转换会产生所需的结果

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vN" select="3"/>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates 
           select="line[position() mod $vN = 1]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="line">
    <set>
      <xsl:apply-templates mode="copy" select= 
       ". 
       | 
        following-sibling::line[position() &lt; $vN]"/>
    </set>
  </xsl:template>

    <xsl:template match="line" mode="copy">
      <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<Header>
    <line>Line 1</line>
    <line>Line 2</line>
    <line>Line 3</line>
    <line>Line 4</line>
    <line>Line 5</line>
    <line>Line 6</line>
    <line>Line 7</line>
    <line>Line 8</line>
    <line>Line 9</line>
</Header>

结果是

<Header>
  <set>
    <line>Line 1</line>
    <line>Line 2</line>
    <line>Line 3</line>
  </set>
  <set>
    <line>Line 4</line>
    <line>Line 5</line>
    <line>Line 6</line>
  </set>
  <set>
    <line>Line 7</line>
    <line>Line 8</line>
    <line>Line 9</line>
  </set>
</Header>

请注意以下

  1. 使用XPath mod运算符查找每组line元素中的第一个vN元素。

  2. 使用模式,以便能够按不同的模板处理不同的line元素

答案 1 :(得分:1)

一般来说,在XSLT中,如果要从列表中创建层次结构,可以使用前面的兄弟和后面的兄弟关键字。如果集合之间存在标记条目,则这很容易。

由于在这种情况下你没有这样的标记我想象一个解决方案可能涉及以下兄弟关键字和mod运算符。提供集合之间划分的mod。

我没试过,但那是我的第一次开始。

xslt通常是了解不同关键字的好地方。

答案 2 :(得分:1)

http://www.xml.com/pub/a/2003/11/05/tr.html使用XSLT 2.0显示了一种稍微不那么难看的方式。关键因素是这一个:

<xsl:for-each-group select="*" group-ending-with="*[position() mod 3 = 0]">

答案 3 :(得分:0)

这应该是可能的。有所需的输出:

<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

  <xsl:template match="/Header">
    <Header>
      <xsl:for-each select="line">
        <xsl:if test="not(number()=0) and position() mod 3 = 0">
          <set>
            <xsl:variable name="pos" select="position()"/>
            <line><xsl:value-of select="../line[position()=($pos -2)]"/></line>
            <line><xsl:value-of select="../line[position()=($pos -1)]"/></line>
            <line><xsl:value-of select="text()"/></line>
            </set>
        </xsl:if>

      </xsl:for-each>
    </Header>
  </xsl:template>

</xsl:stylesheet>

($ pos-1,$ pos-2不太漂亮)