2017-01-26 1 views
0

Из следующих данных XML:с помощью генерации-идентификатор() и ключи, чтобы избавиться от повторов в XSLT

<lieferungen> 
    <artikel id="1111"> 
    <name>apfel</name> 
    <preis stueckpreis="true">8.97</preis> 
    <lieferant>Fa. Krause</lieferant> 
    </artikel> 
    <artikel id="7866"> 
     <name>Kirschen</name> 
     <preis stueckpreis="false">10.45</preis> 
     <lieferant>Fa. Helbig</lieferant> 
    </artikel> 
    <artikel id="3526"> 
     <name>apfel</name> 
     <preis stueckpreis="true">12.67</preis> 
     <lieferant>Fa. Liebig</lieferant> 
    </artikel> 
    <artikel id="7866"> 
     <name>Kirschen</name> 
     <preis stueckpreis="false">17.67</preis> 
     <lieferant>Fa. Krause</lieferant> 
    </artikel> 
    <artikel id="3526"> 
     <name>apfel</name> 
     <preis stueckpreis="true">9.54</preis> 
     <lieferant>Fa. Mertes</lieferant> 
    </artikel> 
    <artikel id="7866"> 
     <name>Kirschen</name> 
     <preis stueckpreis="false">16.45</preis> 
     <lieferant>Fa. Hoeller</lieferant> 
    </artikel> 
    <artikel id="7868"> 
     <name>Kohl</name> 
     <preis stueckpreis="false">3.20</preis> 
     <lieferant>Fa. Hoeller</lieferant> 
    </artikel> 
    <artikel id="7866"> 
     <name>Kirschen</name> 
     <preis stueckpreis="false">12.45</preis> 
     <lieferant>Fa. Richard</lieferant> 
    </artikel> 
    <artikel id="3245"> 
     <name>Bananen</name> 
     <preis stueckpreis="false">15.67</preis> 
     <lieferant>Fa. Hoeller</lieferant> 
    </artikel> 
    <artikel id="6745"> 
     <name>Kohl</name> 
     <preis stueckpreis="false">3.10</preis> 
     <lieferant>Fa. Reinhardt</lieferant> 
    </artikel> 
    <artikel id="7789"> 
     <name>Ananas</name> 
     <preis stueckpreis="true">8.60</preis> 
     <lieferant>Fa. Richard</lieferant> 
    </artikel> 
</lieferungen> 

Я хочу, чтобы создать следующий вывод через XSLT:

Fa. Helbig supplies: Kirschen 

Fa. Liebig supplies: apfel 

Fa. Krause supplies: apfel Kirschen 

Fa. Mertes supplies: apfel 

Fa. Hoeller supplies: Kirschen Kohl Bananen 

Fa. Reinhardt supplies: Kohl 

Fa. Richard supplies: Kirschen Ananas 

С этой целью я написал следующий код xslt:

<?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" 
    exclude-result-prefixes="xs" 
    version="2.0"> 


    <xsl:template match="lieferungen"> 
     <html> 
      <head> 
       <title> 
        <xsl:text>Lieferanten</xsl:text> 
       </title> 
      </head> 
      <body bgcolor="#ffffff"> 
       <h1> 
        <xsl:text>Suppliers</xsl:text> 
       </h1> 
       <hr/> 
       <xsl:apply-templates select="//lieferant"></xsl:apply-templates> 
      </body> 
     </html> 
    </xsl:template> 
    <xsl:template match="lieferant"> 
     <p> 
      <xsl:value-of select="text()"/> 
      <xsl:text> supplies: </xsl:text> 
      <xsl:for-each select="//artikel[lieferant/text() = current()/text()]"> 
       <xsl:value-of select="name/text()"/> 
       <xsl:text></xsl:text> 
      </xsl:for-each> 
     </p> 
    </xsl:template> 


</xsl:stylesheet> 

Это дает мне f ollowing выход:

Fa. Krause supplies: apfelKirschen 
Fa. Helbig supplies: Kirschen 
Fa. Liebig supplies: apfel 
Fa. Krause supplies: apfelKirschen 
Fa. Mertes supplies: apfel 
Fa. Hoeller supplies: KirschenKohlBananen 
Fa. Hoeller supplies: KirschenKohlBananen 
Fa. Richard supplies: KirschenAnanas 
Fa. Hoeller supplies: KirschenKohlBananen 
Fa. Reinhardt supplies: Kohl 
Fa. Richard supplies: KirschenAnanas 

Для того, чтобы избавиться от повторений, я изменил XSLT-кода следующим образом (обратите внимание на комментарии, обозначающие две линии, которые были изменены/добавлены):

<?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" 
     exclude-result-prefixes="xs" 
     version="2.0"> 

     <!--THE FOLLOWING LINE OF CODE WAS ADDED (CHANGE 1/2): --> 
     <xsl:key name="suppliers" match="lieferant" use="lieferant" /> 
      <xsl:template match="lieferungen"> 
      <html> 
       <head> 
        <title> 
         <xsl:text>Lieferanten</xsl:text> 
        </title> 
       </head> 
       <body bgcolor="#ffffff"> 
        <h1> 
         <xsl:text>Suppliers</xsl:text> 
        </h1> 
        <hr/> 

<!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 2/2):-->       
<xsl:apply-templates select="//lieferant[generate-id()=generate-id(key('suppliers', lieferant)[1])]"></xsl:apply-templates> 

       </body> 
      </html> 
     </xsl:template> 
     <xsl:template match="lieferant"> 
      <p> 
       <xsl:value-of select="text()"/> 
       <xsl:text> supplies: </xsl:text> 
       <xsl:for-each select="//artikel[lieferant/text() = current()/text()]"> 
        <xsl:value-of select="name/text()"/> 
        <xsl:text></xsl:text> 
       </xsl:for-each> 
      </p> 
     </xsl:template> 


    </xsl:stylesheet> 

Однако , это нарушило код. Что не так с кодом, который я использовал?

+0

Если (как это кажется), вы» используя XSLT 2.0, почему вы пытаетесь использовать группировку Muenchian? XSLT 2.0 имеет встроенные методы как для группировки, так и для получения различных значений. –

ответ

2

Выход вы хотите, может быть достигнуто довольно просто:

XSLT 2,0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/lieferungen"> 
    <html> 
     <head> 
      <title>Lieferanten</title> 
     </head> 
     <body> 
      <h1>Suppliers</h1> 
      <hr/> 
      <xsl:for-each-group select="artikel" group-by="lieferant"> 
       <p> 
        <xsl:value-of select="current-grouping-key()"/> 
        <xsl:text> supplies: </xsl:text> 
        <xsl:value-of select="current-group()/name"/> 
       </p> 
      </xsl:for-each-group> 
     </body> 
    </html> 
</xsl:template> 

</xsl:stylesheet> 
+0

Большое спасибо за классное решение! – Tommy

1

Если вы используете процессор XSLT 2.0, как таблицы стилей версии указывает на то, видите ответ michael.hor257k в. В противном случае, вот что случилось с вашей таблицей стилей ...

В двух местах, где вы изменили код, контекст был lieferant, но вы пытались использовать значение для ребенка lieferant. В вашем источнике lieferant не имеет ребенка lieferant.

Например, в вашей клавише xsl: вы выбираете lieferant, а также используете lieferant. Когда вы хотите, чтобы use был выбран тот же узел, используйте ..

Это было то же самое и при использовании key(); он использовался внутри предиката на lieferant, поэтому для использования этого контекста используйте ..

Вот ваш обновленный XSLT. Я изменил его в тех же местах, что и вы, но также добавил пространство внутри xsl: text, чтобы отделить name. Я добавил комментарий, указывающий на это изменение, чтобы сохранить его согласованным.

Еще одна вещь, которую я сделал, это изменить версию на 1.0 и удалить неиспользуемое объявление пространства имен xs. (Не реально изменить что-либо в выходе этой таблицы стилей.)

Изменено XSLT 1.0

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <!--THE FOLLOWING LINE OF CODE WAS ADDED (CHANGE 1/3): --> 
    <xsl:key name="suppliers" match="lieferant" use="." /> 
    <xsl:template match="lieferungen"> 
    <html> 
     <head> 
     <title> 
      <xsl:text>Lieferanten</xsl:text> 
     </title> 
     </head> 
     <body bgcolor="#ffffff"> 
     <h1> 
      <xsl:text>Suppliers</xsl:text> 
     </h1> 
     <hr/> 

     <!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 2/3):--> 
     <xsl:apply-templates 
      select="//lieferant[generate-id()=generate-id(key('suppliers', .)[1])]"/> 

     </body> 
    </html> 
    </xsl:template> 
    <xsl:template match="lieferant"> 
    <p> 
     <xsl:value-of select="text()"/> 
     <xsl:text> supplies: </xsl:text> 
     <xsl:for-each select="//artikel[lieferant/text() = current()/text()]"> 
     <xsl:value-of select="name/text()"/> 
     <!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 3/3):--> 
     <xsl:text> </xsl:text> 
     </xsl:for-each> 
    </p> 
    </xsl:template> 

</xsl:stylesheet> 

UPDATE

Как Майкл упоминается в комментарии, вы» повторно теряют половину преимуществ группировки Muenchian с <xsl:for-each select="//artikel[lieferant/text() = current()/text()]">.

Я бы предложил создать ключ, который выбирает уровень artikel и использует в качестве ключа lieferant.

Пример (с комментариями, чтобы указать все изменения) ...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <!--THE FOLLOWING LINE OF CODE WAS ADDED (CHANGE 1/7): --> 
    <xsl:key name="suppliers" match="artikel" use="lieferant" /> 
    <xsl:template match="lieferungen"> 
    <html> 
     <head> 
     <title> 
      <xsl:text>Lieferanten</xsl:text> 
     </title> 
     </head> 
     <body bgcolor="#ffffff"> 
     <h1> 
      <xsl:text>Suppliers</xsl:text> 
     </h1> 
     <hr/> 

     <!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 2/7):--> 
     <xsl:apply-templates 
      select="//artikel[generate-id()=generate-id(key('suppliers', lieferant)[1])]"/> 

     </body> 
    </html> 
    </xsl:template> 
    <!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 3/7):--> 
    <xsl:template match="artikel"> 
    <p> 
     <!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 4/7):--> 
     <xsl:value-of select="lieferant"/> 
     <xsl:text> supplies: </xsl:text> 
     <!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 5/7):--> 
     <xsl:for-each select="key('suppliers',lieferant)"> 
     <!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 6/7):--> 
     <xsl:value-of select="name"/> 
     <!--THE FOLLOWING LINE OF CODE WAS MODIFIED (CHANGE 7/7):--> 
     <xsl:text> </xsl:text> 
     </xsl:for-each> 
    </p> 
    </xsl:template> 

</xsl:stylesheet> 

Однако, вы можете просто изменить XSL: для каждого-:

<xsl:for-each select="key('suppliers',.)"> 
    <xsl:value-of select="../name"/> 
    <xsl:text> </xsl:text> 
</xsl:for-each> 
+1

'' Вы теряете половину преимуществ группировки Muenchian, не повторно используя ключ здесь. –

+0

@ michael.hor257k - Да, это правда. Я тоже это изменю и добавлю примечание к OP. –

Смежные вопросы