Reputation: 516
I need an advice if the way I am trying to implement what I am trying to implement :) is wrong or not. I have an input XML which looks like that:
<somexml>
<item name="name1" />
<item name="name2" />
<item name="name3" />
<item name="name4" />
<item name="name5" />
<item name="name6" />
<item name="name7" />
<item name="name8" />
<item name="name9" />
</somexml>
and I have two XSL templates. First one should only be applied to the first <item>
, and the second one should be applied to the rest of <item>
s grouped by 3, also considering that the last group may (or may not) contain less than 3 elements.
To make it more clear, I should get something like
<template1>name1</template1>
<template2>name2, name3, name4</template2>
<template2>name5, name6, name7</template2>
<template2>name8, name9</template2>
The main question is: is it even possible to achieve that using pure XSLT/XPath or should I fall back to grouping items in the backend code and just outputting them through different XLS templates? Sorry for not publishing my "what have I tried" - it was so ugly and I got rid of it as soon as I realized it would never work :)
Upvotes: 0
Views: 53
Reputation: 117100
The main question is: is it even possible to achieve that using pure XSLT/XPath
Yes, it is possible. But the output you request is not valid XML: you must have a root element.
XSLT 1.0
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/somexml">
<output>
<xsl:apply-templates select="item[1]" />
<xsl:apply-templates select="item[position() > 1][position() mod 3 = 1]" />
</output>
</xsl:template>
<xsl:template match="item[1]">
<template1><xsl:value-of select="@name"/></template1>
</xsl:template>
<xsl:template match="item">
<template2>
<xsl:value-of select="@name"/>
<xsl:if test="following-sibling::item[1]">
<xsl:text>,</xsl:text>
<xsl:value-of select="following-sibling::item[1]/@name"/>
</xsl:if>
<xsl:if test="following-sibling::item[2]">
<xsl:text>,</xsl:text>
<xsl:value-of select="following-sibling::item[2]/@name"/>
</xsl:if>
</template2>
</xsl:template>
</xsl:stylesheet>
Note also that naming your result elements "template" is rather confusing in this context.
Upvotes: 2