2015-06-01 9 views
0

У меня есть XML, как это:Создание алфавитного указателя с фиксированным числом столбцов в XSLT 2.0

<xml version="1.0" encoding="UTF-8"?> 
<countries> 
    <country> 
     <name>Latvia</name> 
    </country> 
    <country> 
     <name>USA</name> 
    </country> 
    <country> 
     <name>Australia</name> 
    </country> 
    <country> 
     <name>Indonesia</name> 
    </country> 
    <country> 
     <name>UK</name> 
    </country> 
    <country> 
     <name>India</name> 
    </country> 
    <country> 
     <name>Argentina</name> 
    </country> 
    <country> 
     <name>Chile</name> 
    </country> 
    <country> 
     <name>Singapore</name> 
    </country> 
    <country> 
     <name>New Zeland</name> 
    </country> 
    <country> 
     <name>Kenya</name> 
    </country> 
    <country> 
     <name>Zambia</name> 
    </country> 
    <country> 
     <name>Tunisia</name> 
    </country> 
</countries> 

Теперь я хочу, чтобы создать алфавитный указатель стран в 3-х колонок. Каждый столбец будет содержать число альфа, как одну треть от начальных алфавитов и соответствующих стран.

Последняя колонка может иметь остальную часть их, если число исходных алфавиты присутствуют случается, не делится на 3.

К примеру, здесь мы название стран, начиная с L, C, U, A, I, S, N, K, Z и T.

После подготовки: ACIKLNSTUZ

Теперь мой индекс будет иметь:

  Column1: A, C and I countries 

     Column2: K, L and N countries 

     Column3: S, T, U and Z countries 

Таким образом, желаемый результат:

<countries> 
    <column1> 
    <A> 
     <country> 
      <name>Argentina</name> 
     </country> 
     <country> 
      <name>Australia</name> 
     </country> 
    </A> 
    <C> 
     <country> 
      <name>Chile</name> 
     </country> 
    </C> 
    <I> 
     <country> 
      <name>India</name> 
     </country> 
     <country> 
      <name>Indonesia</name> 
     </country> 
    </I> 
    </column1> 

    <column2> 
    <K> 
     <country> 
      <name>Kenya</name> 
     </country>  
    </K> 
    <L> 
     <country> 
      <name>Latvia</name> 
     </country> 

    </L> 
    <N> 
     <country> 
      <name>New Zeland</name> 
     </country> 
    </N> 
    </column2> 

    <column3> 
    <S> 
     <country> 
      <name>Singapore</name> 
     </country>  
    </S> 
    <T> 
     <country> 
      <name>Tunisia</name> 
     </country> 

    </T> 
    <U> 
     <country> 
      <name>UK</name> 
     </country> 
     <country> 
      <name>USA</name> 
     </country> 
    </U> 
    <Z> 
     <country> 
      <name>Zambia</name> 
     </country> 
    </Z> 
    </column3> 
</countries> 

Просьба помочь. Я использую xslt 2.0.

+0

ИМХО, вы должны опубликовать новый вопрос с новым требованием. –

+0

Готово. Вот ссылка: http://stackoverflow.com/questions/30614777/adjust-an-alphabetical-index-from-xml-grouping-to-make-columns-equal Спасибо! –

ответ

0

Я придумал

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

<xsl:output indent="yes"/> 

<xsl:param name="size" select="3"/> 

<xsl:template match="countries"> 
    <xsl:copy> 
     <xsl:variable name="groups"> 
     <xsl:for-each-group select="country" group-by="substring(name, 1, 1)"> 
      <xsl:sort select="current-grouping-key()"/> 
      <xsl:element name="{current-grouping-key()}"> 
       <xsl:copy-of select="current-group()"/> 
      </xsl:element>    
     </xsl:for-each-group> 
     </xsl:variable> 
     <xsl:for-each select="$groups/*[position() mod $size eq 1]"> 
     <xsl:if test="position() le $size"> 
      <xsl:variable name="pos" select="position()"/> 
      <xsl:element name="column{position()}"> 
      <xsl:copy-of select="., following-sibling::*[if ($pos eq $size) then true() else (position() lt $size)]"/> 
      </xsl:element> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 


</xsl:transform> 
1

Я хотел бы сделать это в два прохода, сначала сортировать и группировать по букве, задавая последовательность A - Z элементов, а затем разделяем эту последовательность на столбцы.

<xsl:variable name="groups" as="element()*"> 
    <xsl:for-each-group select="/countries/country" group-by="substring(name, 1, 1)"> 
    <!-- sort groups alphabetically --> 
    <xsl:sort select="current-grouping-key()" /> 
    <xsl:element name="{current-grouping-key()}"> 
     <xsl:perform-sort select="current-group()"> 
     <!-- sort names within each group --> 
     <xsl:sort select="name" /> 
     </xsl:perform-sort> 
    </xsl:element> 
    </xsl:for-each-group> 
</xsl:variable> 

<xsl:variable name="numPerCol" select="count($groups) div 3" /> 
<column1> 
    <xsl:sequence select="$groups[position() le $numPerCol]"/> 
</column1> 
<column2> 
    <xsl:sequence select="$groups[position() gt $numPerCol and position() le (2*$numPerCol)]" /> 
</column2> 
<column3> 
    <xsl:sequence select="$groups[position() gt (2*$numPerCol)]" /> 
</column3>