here scenario alphabetical index created 3 columns. but, approach dividing them columns has scope of improvement.
creating alphabetical index fixed number of columns in xslt 2.0
in above scenario, there way if 3 columns can made equal possible without breaking letter group.
i suggest following approach:
xslt 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:param name="columns" select="3"/> <xsl:template match="/countries"> <xsl:variable name="indexed-countries"> <xsl:for-each select="country"> <xsl:sort select="."/> <country index="{position()}"> <xsl:copy-of select="@*|*"/> </country> </xsl:for-each> </xsl:variable> <xsl:variable name="groups"> <xsl:for-each-group select="$indexed-countries/country" group-by="substring(name, 1, 1)"> <group name="{current-grouping-key()}" cumulative-size="{current-group()[last()]/@index}"> <xsl:copy-of select="current-group()"/> </group> </xsl:for-each-group> </xsl:variable> <xsl:variable name="n" select="count(country)" /> <xsl:variable name="col-limit" select="ceiling($n div $columns)" /> <!-- output --> <xsl:copy> <xsl:for-each select="1 $columns"> <xsl:variable name="low" select="(. - 1) * $col-limit" /> <xsl:variable name="high" select=". * $col-limit" /> <xsl:element name="column{.}"> <xsl:copy-of select="$groups/group[$low lt @cumulative-size , @cumulative-size le $high]"/> </xsl:element> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
given input example, result be:
<?xml version="1.0" encoding="utf-8"?> <countries> <column1> <group name="a" cumulative-size="2"> <country index="1"> <name>argentina</name> </country> <country index="2" x="au"> <name>australia</name> </country> </group> <group name="c" cumulative-size="3"> <country index="3"> <name>chile</name> </country> </group> <group name="i" cumulative-size="5"> <country index="4"> <name>india</name> </country> <country index="5"> <name>indonesia</name> </country> </group> </column1> <column2> <group name="k" cumulative-size="6"> <country index="6"> <name>kenya</name> </country> </group> <group name="l" cumulative-size="7"> <country index="7"> <name>latvia</name> </country> </group> <group name="n" cumulative-size="8"> <country index="8"> <name>new zeland</name> </country> </group> <group name="s" cumulative-size="9"> <country index="9"> <name>singapore</name> </country> </group> <group name="t" cumulative-size="10"> <country index="10"> <name>tunisia</name> </country> </group> </column2> <column3> <group name="u" cumulative-size="12"> <country index="11"> <name>uk</name> </country> <country index="12"> <name>usa</name> </country> </group> <group name="z" cumulative-size="13"> <country index="13"> <name>zambia</name> </country> </group> </column3> </countries>
of course, in real implementation, want use xsl-apply-templates
instead of xsl:copy-of
here:
<xsl:copy-of select="$groups/group[$low lt @cumulative-size , @cumulative-size le $high]"/>
to remove "scaffolding" , format output liking.
Comments
Post a Comment