XSLT如何用div包装每个3个元素?

时间:2011-04-09 11:26:42

标签: xml xslt

我有一些带有<item>元素的XML文档,我想在<div>中包含它们中的每一个。如果少于3个元素,也将它们包装起来。

<shop>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  .....
  <item></item>
</shop>

所以结果必须是这样的

<div class="line">
  <item></item>
  <item></item>
  <item></item>
</div>
<div class="line">
  <item></item>
  <item></item>
  <item></item>
</div>
....
<div class="line">
  <item></item>
  <item></item>
</div>

4 个答案:

答案 0 :(得分:1)

可能你的解决方案与此非常相似:

HTML table with alternating row colors via XSL

答案 1 :(得分:1)

  <xsl:for-each select"item">
    <xsl:choose>
      <xsl:when test="count(item) mod 3 = 0">
      </xsl:when>
      <xsl:otherwise>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:foreach>

我没有试过这个,但重要的是foreach循环中的测试。 count(item) mod 3 = 0,而不是每隔三次就能做出反应。

答案 2 :(得分:1)

以下样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--  the number of items to include in each group -->
    <xsl:variable name="group" select="3" />
    <xsl:template match="/">
        <xsl:apply-templates
            select="shop/item[position() mod $group = 1]" />
    </xsl:template>
    <xsl:template match="item" mode="inner">
        <!-- handle items appropriately here -->
        <item/>
    </xsl:template>
    <xsl:template match="item">
        <div class="line">
            <xsl:apply-templates
                select=".|following-sibling::item[position() &lt; $group]"
                mode="inner" />
        </div>
    </xsl:template>
</xsl:stylesheet>

应用于此输入:

<shop>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
  <item></item>
</shop>

产地:

<div class="line">
    <item />
    <item />
    <item />
</div>
<div class="line">
    <item />
    <item />
    <item />
</div>
<div class="line">
    <item />
    <item />
    <item />
</div>
<div class="line">
    <item />
    <item />
    <item />
</div>
<div class="line">
    <item />
    <item />
</div>

答案 3 :(得分:0)

更简单的解决方案

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

 <xsl:template match="item[position() mod 3 = 1]">
  <div>
   <xsl:copy-of select=
    ".|following-sibling::*[not(position() > 2)]"/>
  </div>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<shop>
    <item></item>
    <item></item>
    <item></item>
    <item></item>
    <item></item>
    <item></item>      
    <item></item>
</shop>

生成想要的正确结果

<div>
   <item/>
   <item/>
   <item/>
</div>
<div>
   <item/>
   <item/>
   <item/>
</div>
<div>
   <item/>
</div>

<强>更新

OP已澄清他需要一个转换来处理此页面上的XML文档。除了必须按三个分组并且每个组都包含在<item>中的任何<div>个元素组之外,所有内容都应该按原样复制。

以下是此代码:

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

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="node()[self::item and position() mod 3 = 1]">
   <div>
    <xsl:copy-of select=
    ".|following-sibling::*[not(position()>2)]"/>
   </div>
 </xsl:template>

 <xsl:template match=
  "node()[self::item and not(position() mod 3 = 1)]"/>

</xsl:stylesheet>