Gruppieren und Sortieren
scs
- xsl
Hallo,
ich bin neu hier und habe mit XSL grad angefangen.
Bin also ziemlicher Anfänger und hab folgendes Problem:
Ich möchte ein Telefonbuch bearbeiten:
Es soll nach Postleitzahl gruppiert werden (hab ich schon hinbekommen) und es sollen mehrfache einträge nur einmal angezeigt werden.
Also z.B. ist im unteren Beispiel der Eintrag Bauer, Koenigstr. 1,... doppelt und soll somit einmal nur gezeigt werden.
Hier die XML:
<?xml version="1.0"?>
<addressbook>
<address>
<name>
<last-name>Bauer</last-name>
</name>
<street>Koenig Str.1</street>
<city>Stuttgart</city>
<zip>70188</zip>
</address>
<address>
<name>
<last-name>Bauer</last-name>
</name>
<street>Koenig Str.1</street>
<city>Stuttgart</city>
<zip>70188</zip>
</address>
<address>
<name>
<last-name>Mustermann</last-name>
</name>
<street>Glockenstr.2</street>
<city>Ulm</city>
<zip>61990</zip>
</address>
<address>
<name>
<last-name>Mustermann</last-name>
</name>
<street>Glockenstr.2</street>
<city>Stuttgart</city>
<zip>70327</zip>
</address>
<address>
<name>
<last-name>Mustermann</last-name>
</name>
<street>Ulmer Str.318</street>
<city>München</city>
<zip>70327</zip>
</address>
<address>
<name>
<last-name>Musterfrau</last-name>
</name>
<street>Pragstr. 54</street>
<city>Ulm</city>
<zip>70376</zip>
</address>
</addressbook>
und die bisherige XSL:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:key name="order" match="address" use="zip"/>
<xsl:template match="/">
<table border="1">
<xsl:for-each select="//address[generate-id(.)=
generate-id(key('order', zip)[1])]">
<xsl:sort select="zip"/>
<xsl:for-each select="key('order', zip)">
<xsl:sort select="name/last-name"/>
<xsl:sort select="name/first-name"/>
<tr>
<xsl:if test="position() = 1">
<td valign="center" bgcolor="#999999">
<xsl:attribute name="rowspan">
<xsl:value-of select="count(key('order', zip))"/>
</xsl:attribute>
<b>
xsl:textPLZ </xsl:text><xsl:value-of select="zip"/>
</b>
</td>
</xsl:if>
<td align="right">
xsl:text </xsl:text>
<b><xsl:value-of select="name/last-name"/></b>
</td>
<td>
<xsl:value-of select="street"/>
xsl:text, </xsl:text>
<xsl:value-of select="city"/>
xsl:text, </xsl:text>
<xsl:value-of select="state"/>
xsl:text </xsl:text>
<xsl:value-of select="zip"/>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Würd mich sehr über Hilfe freuen.
Grüße SCS
Hallo,
Es soll nach Postleitzahl gruppiert werden (hab ich schon hinbekommen) und es sollen mehrfache einträge nur einmal angezeigt werden.
Also z.B. ist im unteren Beispiel der Eintrag Bauer, Koenigstr. 1,... doppelt und soll somit einmal nur gezeigt werden.
Im Prinzip willst Du damit doppelt gruppieren: Einmal nach der PLZ und einmal nach der Gesamtadresse. Wenn die Gesamtadresse identisch ist, dann gibst Du sie nur einmal aus (d.h. zeigst nur einen Eintrag für die gesamte Gruppe der gleichen Adresse an).
Du brauchst dafür einen zusätzlichen Schlüssel:
<xsl:key name="addr" match="address" use="." />
Und bei Deiner *inneren* for-Schleife musst Du etwas tricksen. Sie sieht bisher so aus:
<xsl:for-each select="key('order', zip)">
Du willst also jetzt alle Knoten, die key() liefert, nochmal gruppieren, das kannst Du machen, indem Du einfach einen weiteren Qualifier anhängst, z.B. so:
<xsl:for-each select="key('order', zip)[generate-id(.) = generate-id(key('addr', .)[1])]">
Und dann funktioniert's bereits.
Anmerkung: Du kannst statt use="." und key('addr', .) auch sowas wie use="concat(zip, '|', city, '|', street)" und dann entsprechend key('addr', concat(zip, '|', city, '|', street)) verwenden, wenn Du den Schlüssel lieber etwas mehr unter Kontrolle haben willst und Dich nicht auf die automatische String-Konvertierung (und damit auf die richtige Reihenfolge der Knoten im Quelldokument) verlassen willst.
Viele Grüße,
Christian