interne Links in XML
Markus Schntizler
- xml
Ich arbeite erstmals mit XML. Ich möchte auf meiner Homepage eine Liste mit Daten zu Filmen präsentieren und habe zu diesem Zweck ein XML-Dokument mit entsprechender XSL-Datei angelegt. Funktioniert soweit problemlos.
Nun möchte ich am Anfang der Seite eine Liste mit den Filmtiteln einfügen. Von dort sollen interne Links auf den dazugehörigen Abschnitt mit den Daten verweisen. Bei HTML geht das mit <a href="#xyz"> und <a name="xyz">. Wie kann ich etwas ähnliches bei XML einbauen?
Hello out there!
Bei HTML geht das mit <a href="#xyz"> und <a name="xyz">. Wie kann ich etwas ähnliches bei XML einbauen?
?? Wieso bei XML einbauen?
Du lässt dir dieses durch dein XSLT ins HTML einbauen.
Wobei statt <a name="xyz"> auch ein an der entsprechenden Stelle stehendes Element beliebigen Typs die ID "xyz" erhalten kann.
See ya up the road,
Gunnar
?? Wieso bei XML einbauen?
Du lässt dir dieses durch dein XSLT ins HTML einbauen.
Wobei statt <a name="xyz"> auch ein an der entsprechenden Stelle stehendes Element beliebigen Typs die ID "xyz" erhalten kann.
Genau da liegt das Problem. Die internen Links kann ich natürlich in die XLS-Datei einfügen. Aber die Ziele, auf die die internen Links verweisen sollen, sind die Filmtitel. Diese werden jedoch mit xsl:apply-templates/ aus der XML-Datei eingefügt; eines der XML-Tags ist <Titel>. Wo soll ich da das "xyz" einsetzen?
Ich will die internen Links benutzen, damit man gezielt die Infos zu einen bestimmten Film aufrufen kann, ohne mühsam durch das umfangreiche Dokument zu scrollen.
Hello out there!
Genau da liegt das Problem. Die internen Links kann ich natürlich in die XLS-Datei einfügen. Aber die Ziele, auf die die internen Links verweisen sollen, sind die Filmtitel.
Du hast also zwei Schleifen: eine für die Links zu den Ankern, eine für die Linkziele.
Quelldatei:
<?xml-stylesheet type="text/xsl" href="anchors-20060727.xsl"?>
<rdf:RDF
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<rdf:Description rdf:about="http://example.net/foo">
<dc:title>Foo</dc:title>
<dc:description>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</dc:description>
</rdf:Description>
<rdf:Description rdf:about="http://example.net/bar">
<dc:title>Bar Baz</dc:title>
<dc:description>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.</dc:description>
</rdf:Description>
</rdf:RDF>
Stylesheet 'anchors-20060727.xsl':
<xsl:stylesheet version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="/">
<html>
<head>
<title>Anchors</title>
</head>
<body>
<h1>Anchors</h1>
<ol>
<xsl:for-each select="rdf:RDF/rdf:Description">
<li>
<a href="#{translate(dc:title, ' ', '')}">
<xsl:value-of select="dc:title"/>
</a>
</li>
</xsl:for-each>
</ol>
<dl>
<xsl:for-each select="rdf:RDF/rdf:Description">
<dt id="{translate(dc:title, ' ', '')}">
<xsl:value-of select="dc:title"/>
</dt>
<dd>
<xsl:value-of select="dc:description"/>
</dd>
</xsl:for-each>
</dl>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Die http://de.selfhtml.org/xml/darstellung/xpathfunktionen.htm#translate@title=translate-Funktion brauchst du, um gültige Ankernamen zu erzeugen, ggfs. musst du dort weitere Zeichen löschen.
See ya up the road,
Gunnar
Danke für deine ausführliche Antwort. Aber die beiden Dokumente erscheinen mir - zumindest auf den ersten Blick - viel zu kompliziert. Ich bin wie bereits erwähnt Anfänger in Sachen XML und bei dem, was du da schreibst, blicke ich leider nicht durch.
Hello out there!
Danke für deine ausführliche Antwort. Aber die beiden Dokumente erscheinen mir - zumindest auf den ersten Blick - viel zu kompliziert.
Kompliziert? Das eine hat die Struktur
<foo>
<bar>
<baz/>
<quz/>
</bar>
<bar>
<baz/>
<quz/>
</bar>
</foo>
Das kannst du nicht kompliziert nennen. Dass XSLTs kompliziert aussehen, liegt in deren Natur. ;-)
bei dem, was du da schreibst, blicke ich leider nicht durch.
Wenn du eine konkrete Frage hättest ...
See ya up the road,
Gunnar
Das kannst du nicht kompliziert nennen. Dass XSLTs kompliziert aussehen, liegt in deren Natur. ;-)
Für einen XML-Anfänger wie mich sieht das sehr kompliziert aus!
In meinen beiden Dokumenten (.xml und xsl) kommt weder "rdf" noch "dc" noch "foo" noch "bar" noch "baz" oder sonstwas vor. Ich habe ein XML-Dokument mit der typischen Baumstruktur und benannten Tags wie <Titel> etc. Die Daten werden in der XSL-Datei mit "apply templates" eingefügt. Alles andere sind altbekannte HTML-Formatierungen für eine Tabelle etc.
Du bietest mir nun ohne nähere Erläuterungen ein Dokument an, in dem lauter fremde Abkürzungen vorkommen. Da ist es doch logisch, dass ich das nicht verstehe, oder? Das wäre ungefähr so, als würdest du mir einen chinesischen Text vorlegen mit der Begründung: "Du kannst doch Englisch."
Aber wenn es nicht einfacher geht, werde ich zunächst auf solch eine Funktion verzichten und mich allmählich in die komplizierte Welt von XML einarbeiten.
Hallo,
Das kannst du nicht kompliziert nennen. Dass XSLTs kompliziert aussehen, liegt in deren Natur. ;-)
Für einen XML-Anfänger wie mich sieht das sehr kompliziert aus!
In meinen beiden Dokumenten (.xml und xsl) kommt weder "rdf" noch "dc" noch "foo" noch "bar" noch "baz" oder sonstwas vor. Ich habe ein XML-Dokument mit der typischen Baumstruktur und benannten Tags wie <Titel> etc. Die Daten werden in der XSL-Datei mit "apply templates" eingefügt. Alles andere sind altbekannte HTML-Formatierungen für eine Tabelle etc.
Du bietest mir nun ohne nähere Erläuterungen ein Dokument an, in dem lauter fremde Abkürzungen vorkommen. Da ist es doch logisch, dass ich das nicht verstehe, oder? Das wäre ungefähr so, als würdest du mir einen chinesischen Text vorlegen mit der Begründung: "Du kannst doch Englisch."
Aber wenn es nicht einfacher geht, werde ich zunächst auf solch eine Funktion verzichten und mich allmählich in die komplizierte Welt von XML einarbeiten.
Du hast da etwas missverstanden.
Dass die "Abkürzungen" Namensraumprefixe sind, brauchst du im Moment weder wissen noch sollen sie dich weiter stören.
Denke sie dir einfach weg, dann siehst du dass es auch nur ganz normale Elemente sind, die in dem Beispiel vorkommen.
Weder XML noch XSLT ist für den Anfang besonders kompliziert (es sei denn du möchtest gleich irgendwas ausgefallenes - gut Gunnar Beispiel mit dem Namensräumen ist schon etwas gewöhnugsbedürftiger, aber wie gesagt: denke die "Abkürzungen" einfgach weg).
Und wenn du jetzt noch ein Stücken aus deinem XML und XSLT postests, werden wir dir auch besser helfen können, als dass wir dir irgendwelche Beispiele geben, die du noch nicht ganz verstehst.
Grüße
Thomas
Hello out there!
In meinen beiden Dokumenten (.xml und xsl) kommt weder "rdf" noch "dc" noch "foo" noch "bar" noch "baz" oder sonstwas vor.
'rdf' und 'dc' sind – wie Thomas schon sagte – Namensraumpräfixe; 'foo', 'bar', 'baz', 'quz' sind metasyntaktische Variablen.
Ja, sicher heißen deine Elemente anders. Das sollte dich nicht davon abhalten, in verschiedenen Beispielen Äquivalentes auszumachen.
In meinen beiden Beispielen gilt folgende Zuordnung:
rdf:RDF ↔ foo (Wurzelelement)
rdf:Description ↔ bar (Kind)
dc:title ↔ baz (Kindeskind)
dc:description ↔ quz (Kindeskind)
denke die "Abkürzungen" [Namensraumpräfixe] einfgach weg
Oder denke dir einfach den ':' als normales Zeichen im Elementnamen. Dann heißt ein Element halt 'rdf:RDF'.
See ya up the road,
Gunnar
Meine XSL-Datei sieht - auf das wesentliche reduziert - folgendermaßen aus.
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="Abspann">
<HTML>
<head>
<title>MSchnitzler2000</title>
<link rel="stylesheet" type="text/css" href="http://www.mschnitzler2000.de/mschnitzler2000.css" />
</head>
<body>
Hier präsentiere ich meine Film-Datenbank.
<br/>
</body>
</HTML>
</xsl:template>
<xsl:template match="Film">
xsl:apply-templates/
</xsl:template>
<xsl:template match="Titel">
<h1>xsl:apply-templates/</h1>
</xsl:template>
<xsl:template match="Daten1">
<table><tr>xsl:apply-templates/</tr></table>
</xsl:template>
<xsl:template match="Genre">
<td class="abspann" align="right" width="50%"><b>xsl:apply-templates/</b></td>
</xsl:template>
<xsl:template match="Regie">
<td class="abspann" align="left" width="50%">von xsl:apply-templates/</td>
</xsl:template>
<xsl:template match="Daten2">
<table><tr>xsl:apply-templates/</tr></table>
</xsl:template>
<xsl:template match="Land">
<td class="abspann" align="right">xsl:apply-templates/</td>
</xsl:template>
<xsl:template match="Jahr">
<td class="abspann" align="left" width="10%">xsl:apply-templates/</td>
</xsl:template>
<xsl:template match="Laenge">
<td class="abspann" align="left">xsl:apply-templates/ Min.</td>
</xsl:template>
<xsl:template match="Inhalt">
<small>xsl:apply-templates/</small>
</xsl:template>
<xsl:template match="Kritik">
<br /><small><b>xsl:apply-templates/</b></small>
</xsl:template>
<xsl:template match="Links">
<table><tr>xsl:apply-templates/</tr></table>
</xsl:template>
<xsl:template match="IMDB">
<td class="abspann" width="10%"><small><a><xsl:attribute name="href"><xsl:value-of select="." /></xsl:attribute>IMDB</a></small></td>
</xsl:template>
<xsl:template match="Wikipedia">
<td class="abspann"><small><a><xsl:attribute name="href"><xsl:value-of select="." /></xsl:attribute>Wikipedia</a></small></td>
</xsl:template>
</xsl:transform>
Die Daten in der XML-Datei sind folgendermaßen aufgebaut:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="abspann.xsl"?>
<Abspann>
<Film>
<Titel>Anatomie</Titel>
<Daten1>
<Genre>Thriller</Genre>
<Regie>Stefan Ruzowitzky</Regie>
</Daten1>
<Daten2>
<Land>GER</Land>
<Jahr>2000</Jahr>
<Laenge>92</Laenge>
</Daten2>
<Inhalt>Eine Medizinstudentin kommt bei einer Obduktion der Geheimloge der Anti-Hippokraten auf die Spur.</Inhalt>
<Kritik>ein spannender Medizin-Thriller</Kritik>
<Links>
<IMDB>http://german.imdb.com/title/tt0187696/</IMDB>
<Wikipedia>http://de.wikipedia.org/wiki/Anatomie (Film)</Wikipedia>
</Links>
</Film>
<Film>
<Titel>Anatomie 2</Titel>
<Daten1>
<Genre>Thriller</Genre>
<Regie>Stefan Ruzowitzky</Regie>
</Daten1>
<Daten2>
<Land>GER</Land>
<Jahr>2003<Jahr>
<Laenge>94</Laenge>
</Daten2>
<Inhalt>Die Anti-Hippokraten treiben wieder ihr Unwesen.</Inhalt>
<Kritik>Die Fortsetzung des Medizin-Thriller ist so spannend wie der erste Teil.</Kritik>
<Links>
<IMDB>http://german.imdb.com/title/tt0312358/</IMDB>
<Wikipedia>http://de.wikipedia.org/wiki/Anatomie 2</Wikipedia>
</Links>
</Film>
</Abspann>
Was muss ich nun eingeben, um mit internen Links auf die Filmtitel, also die Daten, die mit <Titel> eingefügt werden, zu verlinken?
Hallo,
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
Bist du dir sicher, dass du XSL 2.0 verwenden willst?
<Titel>Anatomie 2</Titel>
...
<Jahr>2003<Jahr>
^^^ Jahr ist nicht beendet
Was muss ich nun eingeben, um mit internen Links auf die Filmtitel, also die Daten, die mit <Titel> eingefügt werden, zu verlinken?
Hier die Änderungen, alles andere bleibt gleich:
-------
<body> Hier präsentiere ich meine Film-Datenbank. <br />
<xsl:apply-templates select="Film" mode="liste" />
<xsl:apply-templates />
</body>
</HTML>
</xsl:template>
<xsl:template match="Film" mode="liste">
<a href="#{translate(Titel, ' ', '')}">
<xsl:value-of select="Titel" />
</a><br />
</xsl:template>
<xsl:template match="Film">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="Titel">
<h1 id="{translate(., ' ', '')}">
<xsl:apply-templates />
</h1>
</xsl:template>
----------
oder wenn du wirklich eine Liste haben willst:
----------
<body> Hier präsentiere ich meine Film-Datenbank. <br />
<ol>
<xsl:for-each select="Film">
<li>
<a href="#{translate(Titel, ' ', '')}">
<xsl:value-of select="Titel" />
</a>
</li>
</xsl:for-each>
</ol>
<xsl:apply-templates />
</body>
</HTML>
</xsl:template>
<xsl:template match="Film">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="Titel">
<h1 id="{translate(., ' ', '')}">
<xsl:apply-templates />
</h1>
</xsl:template>
--------------
Grüße
Thomas
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
Bist du dir sicher, dass du XSL 2.0 verwenden willst?
Die Angaben habe ich aus irgendeinem anderen Dokument übernommen. Ist die Version 2.0 veraltet oder hat die irgendwelche Probleme? Wenn ja, welche Version soll ich nehmen?
------
Ich habe die Änderungen für die Liste in mein Dokument eingefügt, funktioniert problemlos. Allerdings ist die Liste ziemlich lang. Deshalb habe ich die Liste in ein Dropdown-Menü gepackt. Das sieht so aus:
<script language="JavaScript">
function surfto(form)
{
var myindex = form.dest.selectedIndex;
location = form.dest.options[myindex].value;
}
</script>
<form name="myform">
<select name="dest" size="1">
<xsl:for-each select="Film">
<option value="#{translate(Titel, ' ', '')}"><xsl:value-of select="Titel" /></option>
</xsl:for-each>
</select>
<input type="button" value="Start" onClick="surfto(this.form)" /></form>
<xsl:apply-templates />
Danke für eure Hilfe!
Hallo,
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
Bist du dir sicher, dass du XSL 2.0 verwenden willst?
Die Angaben habe ich aus irgendeinem anderen Dokument übernommen. Ist die Version 2.0 veraltet oder hat die irgendwelche Probleme? Wenn ja, welche Version soll ich nehmen?
Im Gegenteil, Version 2.0 ist noch so neu, dass es noch nicht mal eine Spezifikation ist. Du kannst es nehmen, bei deiner Seite sollte es keine Probleme damit geben. Aber 2.0 zu verwenden, wäre erst dann interessant, wenn du ihre Funktionalität auch zu benutzen beabsichtigst (davon würde ich dir aber abraten, denn wenn du das wirklich machst, bekommst du Probleme bei der Darstellung im Browser)
Du kannst einfach version="1.0" verwenden, das ist der aktuelle Stand.
Ich habe die Änderungen für die Liste in mein Dokument eingefügt, funktioniert problemlos. Allerdings ist die Liste ziemlich lang. Deshalb habe ich die Liste in ein Dropdown-Menü gepackt. Das sieht so aus:
Wenn's funktioniert: passt.
Grüße
Thomas
Hallo,
Du lässt dir dieses durch dein XSLT ins HTML einbauen.
Wobei statt <a name="xyz"> auch ein an der entsprechenden Stelle stehendes Element beliebigen Typs die ID "xyz" erhalten kann.
Genau da liegt das Problem. Die internen Links kann ich natürlich in die XLS-Datei einfügen. Aber die Ziele, auf die die internen Links verweisen sollen, sind die Filmtitel. Diese werden jedoch mit xsl:apply-templates/ aus der XML-Datei eingefügt; eines der XML-Tags ist <Titel>. Wo soll ich da das "xyz" einsetzen?
Ich will die internen Links benutzen, damit man gezielt die Infos zu einen bestimmten Film aufrufen kann, ohne mühsam durch das umfangreiche Dokument zu scrollen.
Für solche Fälle empfiehlt sich Templates mit verschiedenen Modi anzulegen:
<xsl:template match="filme" mode="liste">
<a href="#{translate(titel, ' ', '')}">
<xsl:value-of select="titel"/>
</a><br />
</xsl:template>
<xsl:template match="filme" mode="gesamt">
<div id="{translate(titel, ' ', '')}">
bla bla
</div>
</xsl:template>
dann kannst du diese Templates gezielt aufrufen:
<xsl:apply-templates select="filme" mode="liste" />
<xsl:apply-templates select="filme" mode="gesamt" />
Zu translate() hat dir schon Gunnar einiges geschrieben.
Grüße
Thomas
Hallo Thomas,
Für solche Fälle empfiehlt sich Templates mit verschiedenen Modi anzulegen:
So geht das also mit Templates ...
In http://forum.de.selfhtml.org/archiv/2006/6/t131423/#m850630 hast du push processing und pull processing gegenübergestellt. Mir ist zweites (for-each) intuitiver. Ist das Geschmackssache?
Ist beides gleich effektiv? Also, geht alles, was überhaupt geht, in beiden Varianten?
Ist beides gleich effizient? Oder ist das Laufzeitverhalten der einen Variante besser als die der anderen, so dass eventuell je nach Problemstellung sogar mal das eine, mal das andere besser ist?
See ya up the road,
Gunnar
Hallo Gunnar,
Für solche Fälle empfiehlt sich Templates mit verschiedenen Modi anzulegen:
So geht das also mit Templates ...
In http://forum.de.selfhtml.org/archiv/2006/6/t131423/#m850630 hast du push processing und pull processing gegenübergestellt. Mir ist zweites (for-each) intuitiver. Ist das Geschmackssache?
Ist beides gleich effektiv? Also, geht alles, was überhaupt geht, in beiden Varianten?
Ist beides gleich effizient? Oder ist das Laufzeitverhalten der einen Variante besser als die der anderen, so dass eventuell je nach Problemstellung sogar mal das eine, mal das andere besser ist?
ad 1) apply-templates und for-each stellen schon Alternativen dar, so dass man in den meisten Fällen sagen kann, es ist eine Geschmacksache welche man verwendet. Aber "in den meisten Fällen" heisst eben nicht immer. for-each ist gedacht um durch eine Sequenz von Knoten zu iterieren und in dem Sinne ist es also eine Alternative zu apply-templates.
ad 2) for-each ist z.B. dann nützlich, wenn das Ausgangsdokument eine sehr strikte Struktur hat und das Ergebnisdokument auch dementsprechend struriert ist. D.h. wenn man sehr viel über die Struktur des Ausgangsdokuments weiß und das Ergebnis auch entsprechend sein soll.
Nehmen wir dein Beispiel:
Ausgangsdoc.:
rdf:RDF
rdf:Description
dc:title</dc:title>
dc:description</dc:description>
</rdf:Description>
rdf:Description
dc:title</dc:title>
dc:description</dc:description>
</rdf:Description>
</rdf:RDF>
Ergebnisdoc.:
<ol>
<li>
<a></a>
</li>
</ol>
<dl>
<dt></dt>
<dd></dd>
</dl>
Hier ist es kein Problem mit for-each zu arbeiten, denn es gibt nur eine Reihen von rdf:Description-Elementen, die wiederum nur ein dc:titel- gefolgt von einem dc:description-Element enthalten.
Aber wenn das Dokument weniger strikt strukturiert ist, also Elemente in Beileibigen Reihenfolge auftreten können, wäre es ein Problem mit for-each zu arbeiten, es sei denn man will im Ergebnisdokument eine bestimmte Struktur erreichen.
Gruppierungen (vor allem in Verbingung mit der "Muenchian grouping)) in XSLT 1.0 brauchten z.B. (fast) immer for-each, um einen Ausgangsknoten zu haben bzw. die einzelenen Gruppenmitglieder abzuarbeiten (in XSLT 2.0 gilt dies teils auch, aber dort sind die Möglichkeiten viel größer).
Aber auch mit apply-templates sind Gruppierungen möglich:
http://aktuell.de.selfhtml.org/tippstricks/xml/gruppierung1/
for-each und value-of haben den Vorteil, dass man mit denen Knoten direkt ansteuern kann, man kann sie quasi an die gewünste Stelle hereinziehen. Im gegensatz dazu müssen beim apply-templates die entsprechenden Templates erst gesucht werden.
Der Push-Stil (auch pattern-matching oder "rule-based stylesheets" genannt) ist eine der grundlegende Charaktereigenschaften von XSLT.
Damit kann man für jede Art von Knoten Template-Regel erstellen, ohne sich groß um die Struktur gedanken machen zu müssen.
Das mache ich z.B. jetzt wo ich ein XML habe in dem einige Elemente andere in beliebigen Reihenfolge enthalten können und wo andere XML-Dateien mit XInclude eingefügt werden und ich ein Ergebnisdokument brauche das zwar alles einthält, aber noch immer dem Schema entspricht. Ich habe da für alle Elemente Templates geschreiben und durch apply-templates lasse ich dann einfach diese Templates instanziiern. Das wäre mit for-each nicht möglich.
Aber nehmen wir ein Beispiel:
<cd>
<titel>...
<interpret>...
<label>...
<preis>...
</cd>
<xsl:template match="cd">
<tr>
<xsl:apply-templates />
</tr>
</xsl:template>
<xsl:template match="titel | interpret | label | preis">
<td><xsl:value-of select="."/></td>
</xsl:template>
Dies geht so lange gut, bis alles CDs jeweils ein titel | interpret | label | preis-Element enthalten. Wenn dies aber nicht der Fall ist? Dann geht schon die Tabelle flöten.
Also eine Mischung:
<xsl:template match="cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="interpret"/></td>
<td><xsl:value-of select="label"/></td>
<td><xsl:value-of select="preis"/></td>
</tr>
</xsl:template>
Dies hat nicht nur den Vorteil, dass die Tabelle korrekt erstellt wird, sondern auch, dass ich hier genau kontrollieren kann, welche Elemente in welcher Reihenfolge ausgegeben werden.
Natürlich wäre hier auch ein:
<xsl:for-each select="cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="interpret"/></td>
<td><xsl:value-of select="label"/></td>
<td><xsl:value-of select="preis"/></td>
</tr>
</xsl:for-each>
denkbar.
Was aber beim for-each oft vergessen wird, dass man damit den Konktextknoten wechselt (das dies ein sehr oft begangener Fehler ist belegt sogar auch das Archiv hier)
Dann kommt sowas heraus:
<xsl:for-each select="cd">
<tr>
<td><xsl:value-of select="cd/title"/></td>
...
ad 3) Die Effizienz: for-each "kann" etwas besser sein, denn es vermeidet, dass für ein Elemente erst ein Template gesucht und dann ausgeführt werden muss, aber dieser Effekt dürfte sich erst bei _wirklich_ großen Dokumenten messbar auswirken.
Desweiteren macht for-each in machen Fällen das Stylesheet leichter verständlich:
<cd titel="..." interpret="..." label="..." preis="..." />
Da ist ein (vorausgesetzt, mann will alle Attribute als Elemente im Ergebnis haben):
<xsl:for-each select="cd">
<cd>
<xsl:for-each select="@*">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</cd>
</xsl:for-each>
ebenso effizient wie ein:
<xsl:template match="cd">
<cd>
<xsl:apply-templates />
</cd>
</xsl:template>
<xsl:template match="cd/@*">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
trotzdem ist erstere leichter zu lesen.
In den meisten Fällen ist es immer eine Mischung aus den beiden (push u. pull) Stilen die man verwendet. Es ist aber nicht nur Geschmacksache oder Stilfrage, sondern auch Erfahrung wie diese Mischung letztlich aussieht, da manchen mit for-each, maches mit apply-templates einfacher zu erreichen ist.
Grüße
Thomas
... Nachtrag
ad 3) Die Effizienz: for-each "kann" etwas besser sein, denn es vermeidet, dass für ein Elemente erst ein Template gesucht und dann ausgeführt werden muss, aber dieser Effekt dürfte sich erst bei _wirklich_ großen Dokumenten messbar auswirken.
Ich habe interessenhalber mit den Dateien von:
http://aktuell.de.selfhtml.org/tippstricks/xml/gruppierung1/
eine kleine Benchmark gemacht(die for-each Variante des XSL's hänge ich hier unten an):
Ich habe je 10 Versuche gemacht
for-each: Durchschnitt 19ms
http://www.meta-text.net/etc/bm_foreach.gif
apply-templates: Durchschnitt: 25ms
http://www.meta-text.net/etc/bm_applytemplates.gif
Die Zahlen:
1: % der Gesamtzeit kalkuliert im Bezug zum Wurzel (blauer Pfeil) oder zur aufrufenden Anweisung (Uhr)
2: daselbe in µs inkl. Aufruf weiterer Anweisungen
3: % der inhärenten Zeit (zeigt die Zeit die Tatsächlich im Knoten verbraucht wurde) kalkuliert im Bezug zum Wurzel (blauer Pfeil) oder zur aufrufenden Anweisung (Uhr)
4: dasselbe in µs.
x inv.: zeigt wie oft der Knoten aufgerufen wurde bzw. wie oft die anweisung in diesem Teil aufgerufen wurde.
Grüße
Thomas
-------------------------
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="html" encoding="iso-8859-1" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" />
<xsl:key name="participant2event" match="participant" use="id(@events)/@id" />
<xsl:template match="/activity">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>Veranstaltungen und Teilnehmer</title>
</head>
<body>
<h1>Veranstaltungen und Teilnehmer</h1>
<h2>Pro Veranstaltung</h2>
<xsl:for-each select="events/event">
<h3>
<xsl:value-of select="@name" />
</h3>
<ul>
<xsl:for-each select="key('participant2event', @id)">
<li>
<xsl:value-of select="@name" />
</li>
</xsl:for-each>
</ul>
</xsl:for-each>
<hr />
<h2>Pro Teilnehmer</h2>
<xsl:for-each select="participants/participant">
<p>
<strong><xsl:value-of select="@name" />: </strong>
<xsl:for-each select="id(@events)">
<xsl:value-of select="@name" />
<xsl:if test="position() != last()">, </xsl:if>
</xsl:for-each>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>