xslt - Adjust an alphabetical index from xml grouping to make columns equal -


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