使用XSLT 1.0,下面的解決方案是工作 - 測試與您的示例XML 6個元素:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/*">
<xsl:apply-templates select="/foo/bar"/>
</xsl:template>
<xsl:template match="bar">
<xsl:for-each select="*/node()">
<xsl:if test="(position()-1) mod(3) = 0">
<data>
<xsl:call-template name="grouping">
<xsl:with-param name="position" select="position()"/>
<xsl:with-param name="amount" select="3"/>
</xsl:call-template>
</data>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="grouping">
<xsl:param name="position" select="0"/>
<xsl:param name="amount" select="0"/>
<xsl:copy-of select="//bar/*[$position]"/>
<xsl:if test="$amount > $position or ($position mod(3) > 0)">
<xsl:call-template name="grouping">
<xsl:with-param name="position" select="$position + 1"/>
<xsl:with-param name="amount" select="$amount"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
結果:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<A>xxx</A>
<B>yyy</B>
<C>zzz</C>
</data>
<data>
<A>aaa</A>
<B>bbb</B>
<C>ccc</C>
</data>
作爲簡短的說明 - 在模板匹配 「欄中的」 所有元素節點在
<xsl:for-each select="*/node()">
通過使用<xsl:if test="(position()-1) mod(3) = 0">
(w對於第一個節點和第三個節點,其值爲0),稱爲「分組」的模板被稱爲提供3個節點的生成組。這個模板用參數位置(當前節點的位置)和數量 - 要在每個組中複製的節點數量來調用。
分組模板複製當前節點 - <xsl:copy-of select="//bar/*[$position]"/>
- 檢查是否已經生成了3個節點 - <xsl:if test="$amount > $position or ($position mod(3) > 0)">
- 並再次調用自身,以計數器的形式遞增位置,因此下一個節點將被複制。
爲防萬一它不明顯 - 只要不是3的倍數,分組模板將被調用$amount > $position
,所以前3個節點將被複制,並且所有後續節點的$position mod(3) > 0
只要不是3的倍數。在你的xml中第7個元素,這將被複製爲data
-group中的單個元素。
這是*分組*問題(執行搜索)。如果您使用XSLT 1.0或2.0,解決方案會非常不同 - 請選擇一個(這些標籤意味着互斥)。 – 2014-09-29 18:15:18