Ansicht umschalten
Avatar von
  • unbekannter Benutzer

406 Beiträge seit 26.06.2001

Re: XSLT die dümmste Idee überhaupt

Olaf Klischat schrieb am 8. November 2005 0:21

> OK -- du wolltest es nicht anders :)

> (Implementierung des ersten Teils -- d.h. Umsetzung von Liste von
> Artikeln + Liste von Bestellungen in Liste von (Artikel, Anzahl
> Bestellungen))

> > ---eingabe.xml----
> > <data>
> >
> >   <artikel>
> >     <artikelnr>1</artikelnr>
> >     <name>Butterdose</name>
> >     <preis>2.50</preis>
> >   </artikel>
> >   <artikel>
> >     <artikelnr>2</artikelnr>
> >     <name>Geiger-Müller-Zählrohr</name>
> >     <preis>129</preis>
> >   </artikel>
> >   <artikel>
> >     <artikelnr>3</artikelnr>
> >     <name>H-Bombe</name>
> >     <preis>499</preis>
> >   </artikel>
> >   <artikel>
> >     <artikelnr>4</artikelnr>
> >     <name>Luftloch</name>
> >     <preis>12.50</preis>
> >   </artikel>
> >
> >   <bestellung>
> >     <kundennr>1</kundennr>
> >     <artikelnr>2</artikelnr>
> >     <anzahl>3</anzahl>
> >   </bestellung>
> >   <bestellung>
> >     <kundennr>2</kundennr>
> >     <artikelnr>3</artikelnr>
> >     <anzahl>2</anzahl>
> >   </bestellung>
> >   <bestellung>
> >     <kundennr>1</kundennr>
> >     <artikelnr>4</artikelnr>
> >     <anzahl>2</anzahl>
> >   </bestellung>
> >   <bestellung>
> >     <kundennr>2</kundennr>
> >     <artikelnr>3</artikelnr>
> >     <anzahl>5</anzahl>
> >   </bestellung>
> >   <bestellung>
> >     <kundennr>2</kundennr>
> >     <artikelnr>1</artikelnr>
> >     <anzahl>1</anzahl>
> >   </bestellung>
> >   <bestellung>
> >     <kundennr>3</kundennr>
> >     <artikelnr>4</artikelnr>
> >     <anzahl>3</anzahl>
> >   </bestellung>
> >
> > </data>
>
> [viel code]
>
> [...]
> > (relationale Joins, etc. sind nicht die
> > Domaene von XSLT).

> OK, ich wäre dankbar für andere Beispiele :)

Du hast mich schon verstanden. Mathematik, Strin-Operations, Joins
ueber Fremdschluessel (Ok, die sind noch relativ einfach dank XPath,
aber ineffizient), usw. sind nicht die Staerken von XSLT und sollten
nur die Ausnahme sein, ansonsten benutzt man eindeutig das falsche
Werkzeug. XSLT ist zum Transformieren da und arbeitet mit den
Informationen, die man mitgibt, NICHT aber zum Erzeugen (Berechnen)
neuer Informationen. Es ist moeglich, sollte aber nicht die Regel
sein.

Sei's drum, hier ist der XSLT-Ansatz zu deinem Problem. Aufwand: Rund
10 Minuten. XMLSpy unterstuetzt XML-Autocompletion und entsprechend
schnell schreibt man dann, das Summentemplate hatte ich bereits
rumliegen:

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

<!-- start somewhere, match root -->
<xsl:template match="/">
<html>
<head>
<title>Dies ist eine Artikelliste</title>
</head>
<body>
<xsl:for-each select="/data/artikel">
<p>
<xsl:value-of select="concat('Artikel: ', name, ' Bestellungen: ')"
/>
<xsl:call-template name="math_sum">
<xsl:with-param name="nodes" select="/data/bestellung[artikelnr =
current()/artikelnr]" />
</xsl:call-template>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>

<!-- fetch order count of a article node -->
<xsl:template name="get_order_count">
<xsl:param name="node" />
<xsl:value-of select="$node/anzahl" />
</xsl:template>

<!-- calculate sum out of nodeset -->
<xsl:template name="math_sum">
<xsl:param name="nodes" select="/.." />
<xsl:param name="result" select="0" />
<xsl:choose>
<xsl:when test="not($nodes)">
<!-- print result -->
<xsl:value-of select="$result" />
</xsl:when>
<xsl:otherwise>
<!-- fetch value to be summed by template call -->
<xsl:variable name="value">
<xsl:call-template name="get_order_count">
<xsl:with-param name="node" select="$nodes[1]" />
</xsl:call-template>
</xsl:variable>
<!-- recurse to sum rest -->
<xsl:call-template name="math_sum">
<xsl:with-param name="nodes" select="$nodes[position() != 1]" />
<xsl:with-param name="result" select="$result + $value" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

Output:

<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
<title>Dies ist eine Artikelliste</title>
</head>
<body>
<p>Artikel: Butterdose Bestellungen: 1</p>
<p>Artikel: Geiger-Mueller-Zaehlrohr Bestellungen: 3</p>
<p>Artikel: H-Bombe Bestellungen: 7</p>
<p>Artikel: Luftloch Bestellungen: 5</p>
</body>
</html>

Meine Implementation duerfte schneller sein als deine, da die
Rekursive Summenberechnung fuer tail recursion optimization ausgelegt
ist, die jeder heutige XSLT-Prozessunr unterstuetzen sollte.
Schneller deshalb, weil du mit gezinkten Karten spielst und selber
XPath-Expressions benutzt. (Gehoert fuer mich zu XSLT. Wenn schon,
dann arbeite mit einer richtigen XML-API, die eine
Objektrepraesentation generiert, durch die du zwar performant, aber
mit grossem Programmieraufwand surfen musst. Dann gehts auch mit
schnellen SAX-Parsern.) Diese muessen auch erst kompiliert werden und
dann auf einen entsprechend aufbereiteten DOM-Baum angewandt werden.
Dieser Existiert in einer XSLT-Transformation ohnehin schon. 

Bewerten
- +
Ansicht umschalten