2015-06-03 7 views
0

Here - это сценарий, в котором алфавитный указатель создается в 3 столбца. Но подход к делению их на столбцы имеет некоторые улучшения.Откорректируйте алфавитный указатель из группировки xml, чтобы сделать столбцы равными

Creating alphabetical index with fixed number of columns in XSLT 2.0

В приведенном выше сценарии, есть способ, если 3 колонки могут быть выполнены в максимально равно, насколько это возможно, не нарушая письмо группы.

ответ

1

Я хотел бы предложить следующий подход:

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 to $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 and @cumulative-size le $high]"/> 
      </xsl:element> 
     </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

Учитывая ваш вклад, например, результат будет:

<?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> 

Конечно, в реальной реализации, вам нужно будет использовать xsl-apply-templates вместо xsl:copy-of здесь:

<xsl:copy-of select="$groups/group[$low lt @cumulative-size and @cumulative-size le $high]"/> 

удалить «строительные леса» и формат вывода по своему вкусу.