XSL — группировка на основе свойств элемента

Как сгруппировать элементы ниже, используя «insref» и «pref». Я пытался использовать идентификатор ключа генерации в xslt версии 1.

XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
   <mylist>
    <cd id="1" insref="#10">
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd id ="2" insref="#20" pref="#1">
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd id="3" insref="#520" pref="#1">
        <title>Lonly heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd id="4" insref="#56" pref="#1">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
    <cd id="5" insref="#56" pref="#2">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
    <cd id="6" insref="#56" pref="#2">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
    <cd id="7" insref="#56" pref="#2">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
    <cd id="8" insref="#78" pref="#2">
        <title>Maggie May</title>
        <artist>Rod Stewart</artist>
        <country>UK</country>
        <company>Pickwick</company>
        <price>8.50</price>
        <year>1990</year>
    </cd>
    <cd id="9" insref="#45" pref="#1">
        <title>Romanza</title>
        <artist>Andrea Bocelli</artist>
        <country>EU</country>
        <company>Polydor</company>
        <price>10.80</price>
        <year>1996</year>
    </cd>

    <cd id="10" insref="#45" pref="#2">
        <title>Romanza</title>
        <artist>Andrea Bocelli</artist>
        <country>EU</country>
        <company>Polydor</company>
        <price>10.80</price>
        <year>1996</year>
    </cd>
 </mylist>  
</catalog>

Желаемый результат:

TITLE               ARTIST          ID  INSREF  PREF    Qty
Empire Burlesque    Bob Dylan       1   10      
Hide your heart     Bonnie Tyler    2   20      1       1   
Lonly heart         Bonnie Tyler    3   520     1       1       
Still got the blues Gary Moore      4   56      1       1   
Still got the blues Gary Moore      4   56      2       3   
Maggie May          Rod Stewart     8   78      2       1   
Romanza             Andrea Bocelli  9   45      1       1
Romanza             Andrea Bocelli  10  45      2       1

Вот что у меня есть. Я также использую функцию генерации ключей. Любая идея, что не так с этим xslt. Что касается подсчета, я думал о том, чтобы получить уникальное количество ключей.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="by-accessRefs" match="cd" use="concat(@insref,@pref)"/>

<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Artist</th>
        <th>INSREF</th>
         <th>PREF</th>
      </tr>
      <xsl:for-each select="catalog/mylist/cd[generate-id(.) = generate-id(key('by-accessRefs',concat(@insref,@pref)[1])]">

         <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="artist"/></td>
        <td><xsl:value-of select="@insref"/></td>
        <td><xsl:value-of select="@pref"/></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

person renni eappen    schedule 29.04.2012    source источник
comment
что ты уже испробовал? Покажите нам XSL, который вы используете, и объясните, почему он не работает.   -  person Jim Garrison    schedule 29.04.2012
comment
Вы используете XSLT1.0 или XSLT2.0? Это отличается от того, как вы группируете здесь.   -  person Tim C    schedule 29.04.2012


Ответы (2)


Это преобразование XSLT 1.0:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kCDByProps" match="cd" use=
  "concat(title,'+',artist,'+',@insref,'+',@pref)"/>

 <xsl:template match="/*">
     <table>
       <thead>
         <tr>
           <td>TITLE</td><td>ARTIST</td><td>ID</td><td>INSREF</td><td>PREF</td><td>Qty</td>
         </tr>
       </thead>
       <xsl:apply-templates select=
        "mylist/cd
            [generate-id()
            =
             generate-id(key('kCDByProps', 
                               concat(title,'+',artist,'+',@insref,'+',@pref)
                              )[1])
            ]
        "/>
     </table>
 </xsl:template>

 <xsl:template match="cd">
  <xsl:variable name="vGroup" select=
    "key('kCDByProps', concat(title,'+',artist,'+',@insref,'+',@pref))"/>

  <tr>
    <td><xsl:value-of select="title"/></td>
    <td><xsl:value-of select="artist"/></td>
    <td><xsl:value-of select="@id"/></td>
    <td><xsl:value-of select="substring(@insref, 2)"/></td>
    <td><xsl:value-of select="substring(@pref, 2)"/></td>
    <xsl:variable name="vCount" select=
           "count($vGroup[@pref = current()/@pref])"/>
    <td>
        <xsl:if test="$vCount"><xsl:value-of select="$vCount"/></xsl:if>
    </td>
  </tr>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному XML-документу:

<catalog>
    <mylist>
        <cd id="1" insref="#10">
            <title>Empire Burlesque</title>
            <artist>Bob Dylan</artist>
            <country>USA</country>
            <company>Columbia</company>
            <price>10.90</price>
            <year>1985</year>
        </cd>
        <cd id ="2" insref="#20" pref="#1">
            <title>Hide your heart</title>
            <artist>Bonnie Tyler</artist>
            <country>UK</country>
            <company>CBS Records</company>
            <price>9.90</price>
            <year>1988</year>
        </cd>
        <cd id="3" insref="#520" pref="#1">
            <title>Lonly heart</title>
            <artist>Bonnie Tyler</artist>
            <country>UK</country>
            <company>CBS Records</company>
            <price>9.90</price>
            <year>1988</year>
        </cd>
        <cd id="4" insref="#56" pref="#1">
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
            <country>UK</country>
            <company>Virgin records</company>
            <price>10.20</price>
            <year>1990</year>
        </cd>
        <cd id="5" insref="#56" pref="#2">
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
            <country>UK</country>
            <company>Virgin records</company>
            <price>10.20</price>
            <year>1990</year>
        </cd>
        <cd id="6" insref="#56" pref="#2">
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
            <country>UK</country>
            <company>Virgin records</company>
            <price>10.20</price>
            <year>1990</year>
        </cd>
        <cd id="7" insref="#56" pref="#2">
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
            <country>UK</country>
            <company>Virgin records</company>
            <price>10.20</price>
            <year>1990</year>
        </cd>
        <cd id="8" insref="#78" pref="#2">
            <title>Maggie May</title>
            <artist>Rod Stewart</artist>
            <country>UK</country>
            <company>Pickwick</company>
            <price>8.50</price>
            <year>1990</year>
        </cd>
        <cd id="9" insref="#45" pref="#1">
            <title>Romanza</title>
            <artist>Andrea Bocelli</artist>
            <country>EU</country>
            <company>Polydor</company>
            <price>10.80</price>
            <year>1996</year>
        </cd>
        <cd id="10" insref="#45" pref="#2">
            <title>Romanza</title>
            <artist>Andrea Bocelli</artist>
            <country>EU</country>
            <company>Polydor</company>
            <price>10.80</price>
            <year>1996</year>
        </cd>
    </mylist>
</catalog>

выводит следующий HTML-выход:

<table>
   <thead>
      <tr>
         <td>TITLE</td>
         <td>ARTIST</td>
         <td>ID</td>
         <td>INSREF</td>
         <td>PREF</td>
         <td>Qty</td>
      </tr>
   </thead>
   <tr>
      <td>Empire Burlesque</td>
      <td>Bob Dylan</td>
      <td>1</td>
      <td>10</td>
      <td/>
      <td/>
   </tr>
   <tr>
      <td>Hide your heart</td>
      <td>Bonnie Tyler</td>
      <td>2</td>
      <td>20</td>
      <td>1</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Lonly heart</td>
      <td>Bonnie Tyler</td>
      <td>3</td>
      <td>520</td>
      <td>1</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Still got the blues</td>
      <td>Gary Moore</td>
      <td>4</td>
      <td>56</td>
      <td>1</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Still got the blues</td>
      <td>Gary Moore</td>
      <td>5</td>
      <td>56</td>
      <td>2</td>
      <td>3</td>
   </tr>
   <tr>
      <td>Maggie May</td>
      <td>Rod Stewart</td>
      <td>8</td>
      <td>78</td>
      <td>2</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Romanza</td>
      <td>Andrea Bocelli</td>
      <td>9</td>
      <td>45</td>
      <td>1</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Romanza</td>
      <td>Andrea Bocelli</td>
      <td>10</td>
      <td>45</td>
      <td>2</td>
      <td>1</td>
   </tr>
</table>

который при просмотре в браузере кажется правильным результатом:

введите здесь описание изображения

person Dimitre Novatchev    schedule 29.04.2012
comment
Спасибо Димитр! это сработало. Я пробовал что-то подобное, но у меня это не сработало ... Я опубликовал это как обновление, вы можете увидеть, где я ошибся. Спасибо еще раз ! - person renni eappen; 29.04.2012
comment
@rennieappen: Добро пожаловать. Я просмотрел ваш код и обнаружил синтаксические ошибки, о которых процессор XSLT должен сообщить вам. Тогда вам нужно исправить их. - person Dimitre Novatchev; 29.04.2012
comment
Спасибо, сэр. Я использую онлайн-редактор w3 school. Не очень помогает с синтаксическими ошибками. Как вы упомянули, мне нужен хороший редактор. - person renni eappen; 29.04.2012
comment
@rennieappen: Saxon 6.5.x — хороший процессор XSLT 1.0 XSLT. Если вы новичок в XSLT, я бы порекомендовал начать с XSLT 2.0 — Saxon 9 — хороший выбор. Kernow — это графический интерфейс к Saxon. Если вы ограничены использованием XSLT 1.0 и у вас есть Visual Studio, вы можете использовать его редактор XML в сочетании с отладчиком XSLT. Другой вариант (как с XSLT 1.0, так и с XSLT 2.0) — oXygen. - person Dimitre Novatchev; 29.04.2012
comment
Спасибо, что поделились этой информацией. Ценю всю помощь. - person renni eappen; 29.04.2012

Я предположил, что вам нужна таблица HTML:

Файл таблицы стилей

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
    exclude-result-prefixes="xs xd"
    version="2.0">

    <xsl:output method="html" indent="yes"/>

    <xsl:key name="kTitle" match="title" use="text()"/>

    <xsl:template match="/">
        <table>
            <thead>
                <tr>
                    <th>TITLE</th>
                    <th>ARTIST</th>
                    <th>ID</th>
                    <th>INSREF</th>
                    <th>PREF</th>
                    <th>Qty</th>
                </tr>
            </thead>
            <tbody>
                <xsl:for-each-group select="//cd" group-by="@id">
                    <tr>
                        <td><xsl:value-of select="title"/></td>
                        <td><xsl:value-of select="artist"/></td>
                        <td><xsl:value-of select="@id"/></td>
                        <td><xsl:value-of select="substring-after(@insref,'#')"/></td>
                        <td><xsl:value-of select="substring-after(@pref,'#')"/></td>
                        <td><xsl:value-of select="count(key('kTitle',title/text()))"/></td>
                    </tr>
                </xsl:for-each-group>
            </tbody>
        </table>
    </xsl:template>

</xsl:stylesheet>

Результирующий документ:

<table>
   <thead>
      <tr>
         <th>TITLE</th>
         <th>ARTIST</th>
         <th>ID</th>
         <th>INSREF</th>
         <th>PREF</th>
         <th>Qty</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>Empire Burlesque</td>
         <td>Bob Dylan</td>
         <td>1</td>
         <td>10</td>
         <td></td>
         <td>1</td>
      </tr>
      <tr>
         <td>Hide your heart</td>
         <td>Bonnie Tyler</td>
         <td>2</td>
         <td>20</td>
         <td>1</td>
         <td>1</td>
      </tr>
      <tr>
         <td>Lonly heart</td>
         <td>Bonnie Tyler</td>
         <td>3</td>
         <td>520</td>
         <td>1</td>
         <td>1</td>
      </tr>
      <tr>
         <td>Still got the blues</td>
         <td>Gary Moore</td>
         <td>4</td>
         <td>56</td>
         <td>1</td>
         <td>4</td>
      </tr>
      <tr>
         <td>Still got the blues</td>
         <td>Gary Moore</td>
         <td>5</td>
         <td>56</td>
         <td>2</td>
         <td>4</td>
      </tr>
      <tr>
         <td>Still got the blues</td>
         <td>Gary Moore</td>
         <td>6</td>
         <td>56</td>
         <td>2</td>
         <td>4</td>
      </tr>
      <tr>
         <td>Still got the blues</td>
         <td>Gary Moore</td>
         <td>7</td>
         <td>56</td>
         <td>2</td>
         <td>4</td>
      </tr>
      <tr>
         <td>Maggie May</td>
         <td>Rod Stewart</td>
         <td>8</td>
         <td>78</td>
         <td>2</td>
         <td>1</td>
      </tr>
      <tr>
         <td>Romanza</td>
         <td>Andrea Bocelli</td>
         <td>9</td>
         <td>45</td>
         <td>1</td>
         <td>2</td>
      </tr>
      <tr>
         <td>Romanza</td>
         <td>Andrea Bocelli</td>
         <td>10</td>
         <td>45</td>
         <td>2</td>
         <td>2</td>
      </tr>
   </tbody>
</table>
person Cylian    schedule 29.04.2012