Сортировка в XSLT осуществляется прямолинейно. На самом деле вам действительно нужно знать, как «группировать» предметы. Как отметил Майкл Кей, в XSLT 2.0 это намного проще, чем в XSLT 1.0. В XSLT 1.0 вы склонны использовать метод Muenchian Grouping, который кажется запутанным, когда вы его впервые видите, но, как правило, это самый эффективный способ сделать это.
С точки зрения вашего вывода вы делаете две партии группировки. Во-первых, по первой букве, либо группа/код (если она существует), либо название.
Muenchian Grouping работает, определяя ключ, чтобы обеспечить быстрый поиск всех элементов в группе. Для первой буквы eithe группы/код или название, вы должны определить это как так
<xsl:key name="letter" match="info" use="substring(concat(group/code, title), 1, 1)"/>
(Примечание: Это чувствительно к регистру, поэтому вам, возможно, придется использовать функцию «перевод» если вы могут иметь сочетание букв с нижним и верхним регистрами).
Если группы/код существует, то он будет использовать первую букву, что, в противном случае он подберет первую букву титула.
Для группы/код или титула самих, ключ будет выглядеть следующим образом
<xsl:key name="info" match="info" use="title[not(../group)]|group/code"/>
Таким образом, он использует только «название» элементы там, где нет «группы» элемент присутствует.
Чтобы получить отдельные первые буквы для вашей первой группировки, вы выбираете все элементы info и проверяете, являются ли они первым элементом в ключе для данной буквы. Это делается вот так
<xsl:apply-templates
select="info
[generate-id()
= generate-id(key('letter', substring(concat(group/code, title), 1, 1))[1])]"
mode="letter">
<xsl:sort select="substring(concat(group/code, title), 1, 1)" />
</xsl:apply-templates>
«режим» используется здесь, так как окончательный XSLT будет шаблонам соответствующих информации.
В шаблоне соответствия, группировать либо кода/группы или название вы можете сделать это
<xsl:apply-templates
select="key('letter', $letter)
[generate-id() = generate-id(key('info', title[not(../group)]|group/code)[1])]">
<xsl:sort select="title[not(../group)]|group/code" />
</xsl:apply-templates>
И, наконец, чтобы вывести все элементы, входящие в последней группе, вы бы просто снова используйте ключ
<xsl:apply-templates select="key('info', $value)[group/code=$value]/title">
Полный XSLT.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:key name="letter" match="info" use="substring(concat(group/code, title), 1, 1)"/>
<xsl:key name="info" match="info" use="title[not(../group)]|group/code"/>
<xsl:template match="/*">
<xsl:apply-templates select="info[generate-id() = generate-id(key('letter', substring(concat(group/code, title), 1, 1))[1])]" mode="letter">
<xsl:sort select="substring(concat(group/code, title), 1, 1)" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="info" mode="letter">
<xsl:variable name="letter" select="substring(concat(group/code, title), 1, 1)" />
<xsl:value-of select="concat($letter, ' ')" />
<xsl:apply-templates select="key('letter', $letter)[generate-id() = generate-id(key('info', title[not(../group)]|group/code)[1])]">
<xsl:sort select="title[not(../group)]|group/code" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="info">
<xsl:variable name="value" select="title[not(../group)]|group/code" />
<xsl:value-of select="concat($value, ' ')" />
<xsl:apply-templates select="key('info', $value)[group/code=$value]/title">
<xsl:sort select="." />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="title">
<xsl:value-of select="concat(' ', ., ' ')" />
</xsl:template>
</xsl:stylesheet>
Применительно к вашему XML, следующий выход
A
Auto2
Auto3
Auto4
Certificate
Auto5
s
state
Auto
Bill
Есть ли действительно никакого способа, вы можете перейти к XSLT 2.0? Это делает эту проблему намного проще ... –
Мы строго используем xslt1.0..Нет способа использовать xslt2.0 – Blossom