I have some XML document with <item>
elements, and i'd want to wrap each 3 of them in <div>
If there is less than 3 elements, wrap them too.
<shop>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
.....
<item></item>
</shop>
So result must be something like this
<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>
Probably your solution will be very similar to this:
HTML table with alternating row colors via XSL
The following stylesheet:
<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() < $group]"
mode="inner" />
</div>
</xsl:template>
</xsl:stylesheet>
Applied to this input:
<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>
Produces:
<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>
<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>
I haven't tried this, but important is the test in the foreach loop. count(item) mod 3 = 0
than you can react every third time.
A much simpler solution:
<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>
when applied on the provided XML document:
<shop>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
</shop>
produces the wanted, correct result:
<div>
<item/>
<item/>
<item/>
</div>
<div>
<item/>
<item/>
<item/>
</div>
<div>
<item/>
</div>
Update:
The OP has clarified that he needs a transformation that would process the XML document on this page. Everything should be copied as-is with the exception of any group of <item>
elements that must be grouped by three and each group wrapped into a <div>
.
Here is the code for this:
<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>
精彩评论