2009-11-10 18 views
6

tengo al lado xml:Agrupación por 2 campos en XSL

<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> 

y necesito transformarla en html. Los registros se deben agrupar por id y cur. Y después de cada grupo, debe mostrarse la cantidad total. Entonces queremos algo como esto:

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 
... 

¿Cómo puedo lograr esto usando XSL?

Cuando traté de encontrar una respuesta en google, encontré el método de Muenchian, pero es muy complicado cuando queremos agrupar el resultado en 2 campos. Soy principiante en xsl y es un poco difícil para mí. También encontré el operador xslt 2.0 para cada grupo. ¿Es compatible con los principales navegadores? ¿Normalmente es para usarlo o solo debemos confiar en xslt 1.0?

+0

XSLT 2.0 no es tan generalizado todavía, y confiar en que sería un error, a menos que se puede controlar donde la transformación se lleva a cabo. Si yo fuera tú, lo pensaría seriamente y realmente consideraría ubicar la transformación en el lado del servidor. –

+0

No, desafortunadamente no puedo hacer eso, la transformación debe ser del lado del cliente (no es mi decisión) – Roman

+0

Conozco la sensación, nunca he tenido éxito tratando de ejecutar transformaciones en el lado del cliente, al menos no con cualquier compatibilidad de navegador cruzado. –

Respuesta

3

Usted puede hacer esto con XSLT 1.0

el método que utilizo aquí es crear una clave compuesta con los dos campos, ID y act. Luego, aplico las plantillas al primer documento en cada grupo. Dentro de la plantilla, recorro los documentos individuales y finalmente resumo el campo de cantidad de documentos.

<?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> 

Salida:

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

En aras de la legibilidad del código, recomiendo usar '' sobre cadenas literales en el XSL. De esta forma, el formato de salida es mucho más fácil de controlar y el formato del código puede tener sangrías correctas. – Tomalak

+0

¡Punto válido! Pero siento que esta no es la solución final de todos modos. –

+0

¡Muchas gracias! No solo es una buena solución, sino también un ejemplo útil para toda la teoría que he leído antes sobre xsl. – Roman

0

Concatening dos campos para crear una clave compuesta no es seguro, a menos que esté absolutamente seguro de todas las dichas claves creadas son únicos. Este método es más seguro, pienso:

<?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>