2009-11-10 8 views
6

XSL J'ai ensuite xml:Regroupement par 2 champs

<page> 
    <document> 
     <id>1001</id> 
     <cur>USD</cur> 
     <date>01.01.2009</date> 
     <amount>10</amount> 
    </document> 
    <document> 
     <id>1001</id> 
     <cur>USD</cur> 
     <date>02.01.2009</date> 
     <amount>15</amount> 
    </document> 
    <document> 
     <id>1001</id> 
     <cur>JPY</cur> 
     <date>01.01.2009</date> 
     <amount>5</amount> 
    </document> 
    <document> 
     <id>1002</id> 
     <cur>USD</cur> 
     <date>01.01.2009</date> 
     <amount>5</amount> 
    </document> 
    ... 
</page> 

Et je dois le transformer en html. Les enregistrements doivent être regroupés par id et cur. Et après chaque groupe, le montant total devrait être indiqué. Donc, nous voulons quelque chose comme ceci:

Bill: id=1001, cur=USD 
     date=01.01.2009 amount=10 
     date=02.01.2009 amount=15 
     total amount=25 
Bill: id=1001, cur=JPY 
     date=01.01.2009 amount=5 
     total amount=5 
Bill: id=1002, cur=USD 
     date=01.01.2009 amount=5 
     total amount=5 
... 

Comment puis-je réaliser cela en utilisant XSL?

Lorsque j'ai essayé de trouver la réponse dans google j'ai trouvé la méthode Muenchian, mais c'est trop compliqué quand on veut regrouper le résultat par 2 champs. Je suis débutant en xsl et c'est un peu difficile pour moi. J'ai également trouvé l'opérateur xslt 2.0 pour chaque groupe. Est-il pris en charge par les principaux navigateurs? Est-ce normalement pour l'utiliser ou nous devrions seulement compter sur xslt 1.0?

+0

XSLT 2.0 n'est pas encore répandue, et à se fier que ce serait une erreur, à moins que vous pouvez contrôler où la transformation a lieu. Si j'étais vous, j'y réfléchirais sérieusement et envisagerais de placer la transformation sur le serveur. –

+0

Non, malheureusement, je ne peux pas faire cela, la transformation devrait être du côté client (ce n'est pas ma décision) – Roman

+0

Je connais le sentiment, je n'ai jamais eu de succès en essayant d'exécuter des transformations du côté client, de peur que non toute compatibilité cross-navigateur. –

Répondre

3

Vous pouvez le faire avec XSLT 1.0

La méthode que je l'utilise ici est de créer une clé composite avec les deux champs, id et cabot. J'applique plus tard les modèles au premier document de chaque groupe. Dans le modèle, je fais ensuite une boucle dans les documents individuels et finalement je résume le champ de quantité de documents.

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

<xsl:key name="idcur" match="document" use="concat(id,cur)"/> 

<xsl:template match="/page"> 
    <xsl:apply-templates select="document[generate-id() = generate-id(key('idcur',concat(id,cur))[1])]"/> 
</xsl:template> 

<xsl:template match="document"> 
<xsl:variable name="document" select="key('idcur',concat(id,cur))"/> 
Bill: id=<xsl:value-of select="id"/>, cur=<xsl:value-of select="cur"/> 
    <xsl:for-each select="$document"> 
     date=<xsl:value-of select="date"/> amount=<xsl:value-of select="amount"/> 
    </xsl:for-each> 
     total amount=<xsl:value-of select="sum($document/amount)"/> 
</xsl:template> 
</xsl:stylesheet> 

Sortie:

Bill: id=1001, cur=USD 
     date=01.01.2009 amount=10 
     date=02.01.2009 amount=15 
     total amount=25 
Bill: id=1001, cur=JPY 
     date=01.01.2009 amount=5 
     total amount=5 
Bill: id=1002, cur=USD 
     date=01.01.2009 amount=5 
     total amount=5 
+0

Par souci de lisibilité du code, je recommande d'utiliser '' sur les chaînes littérales du XSL. De cette façon, le format de sortie est beaucoup plus facilement contrôlé, et le format de code peut avoir des retraits corrects. – Tomalak

+0

Point valide! Mais je pense que ce n'est pas la solution finale de toute façon. –

+0

Merci beaucoup! Ce n'est pas seulement une bonne solution mais aussi un exemple utile pour toute la théorie que j'ai déjà lu sur xsl. – Roman

0

Concatening deux champs pour créer une clé composite est pas sûr, sauf si vous êtes absolument sûr toutes les clés telles créées sont uniques. Cette méthode est plus sûre, je pense:

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

<xsl:output method="text"/> 

<xsl:key name="ids" match="document" use="id"/> 
<xsl:key name="currencies" match="document" use="cur"/> 

<xsl:template match="/page"> 
    <xsl:apply-templates select="document[generate-id() = generate-id(key('ids',id)[1])]"/> 
</xsl:template> 

<xsl:template match="document"> 
    <xsl:for-each select="key('ids',id)[generate-id() = generate-id(key('currencies', cur)[id=current()/id][1])]"> 
    <xsl:variable name="bills" select="key('ids', id)[cur = current()/cur]"/> 
    <xsl:text>Bill: id=</xsl:text> 
    <xsl:value-of select="id"/> 
    <xsl:text>, cur=</xsl:text> 
    <xsl:value-of select="cur"/> 
    <xsl:for-each select="$bills"> 
     <xsl:text>&#10;date=</xsl:text> 
     <xsl:value-of select="date"/> 
     <xsl:text> amount=</xsl:text> 
     <xsl:value-of select="amount"/> 
    </xsl:for-each> 
    <xsl:text>&#10;total amount=</xsl:text> 
    <xsl:value-of select="sum($bills/amount)"/> 
    <xsl:text>&#10;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet>