2013-07-24 3 views
3

Input XML:Сортировка данных в порядке алфавитного XML

<?xml version="1.0" encoding="utf-8" ?> 
<infoset> 
    <info> 
    <title>Bill</title> 
    <group> 
     <code>state</code> 
    </group> 
    </info> 
    <info> 
    <title>Auto</title> 
    <group> 
     <code>state</code> 
    </group> 
    </info> 
    <info> 
    <title>Auto2</title> 
    </info> 
    <info> 
    <title>Auto3</title> 
    </info> 
    <info> 
    <title>Auto5</title> 
    </info> 
    <info> 
    <title>Certificate</title> 
    <group> 
     <code>Auto4</code> 
    </group> 
    </info> 
    </infoset> 

Ожидаемый результат:

A 

Auto2 
Auto3 
Auto4 
    Certificate 
Auto5 

S 
state 
    Auto 
    Bill 

Мне нужно организовать название и код в алфавитном порядке order.If инфо имеет группу плитку РЕКОМЕНДУЕМУЮ подпадают под группу. Я использую visual studio2010, xslt1.0 Processor и xml editor.

+0

Есть ли действительно никакого способа, вы можете перейти к XSLT 2.0? Это делает эту проблему намного проще ... –

+0

Мы строго используем xslt1.0..Нет способа использовать xslt2.0 – Blossom

ответ

1

Сортировка в 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, '&#10;')" /> 
    <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, '&#10;')" /> 
    <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(' ', ., '&#10;')" /> 
    </xsl:template> 
</xsl:stylesheet> 

Применительно к вашему XML, следующий выход

A 
Auto2 
Auto3 
Auto4 
    Certificate 
Auto5 
s 
state 
    Auto 
    Bill 
Смежные вопросы