XSL Problem: Kontextknoten nicht bekannt?
Julia
- xml
- xsl
Hallo zusammen,
ich möchte aud XML ein HTML bauen. Ich habe folgende XML-Datei für Bücher:
<?xml version="1.1" encoding="UTF-8"?>
<library xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='library.xsd'>
<book>
<author-ref>J.K.Rowling</author-ref>
<title>Harry Potter und der Stein der Weisen</title>
<language>de</language>
<year>1998</year>
</book>
<book>
<author-ref>J.K.Rowling</author-ref>
<title>Harry Potter und die Kammer des Schreckens</title>
<language>de</language>
<year>1999</year>
</book>
...
Daraus möchte ich sozusagen einen Glossar bauen:
z.B.:
H
Harry
Harry Potter und der Stein der Weisen
Harry Potter und die Kammer des Schreckens
K
Kammer
Harry Potter und die Kammer des Schreckens
usw.
Ich habe bereis geschafft,die Buchtsaben und Suchwörter sortiert auszugeben.
und möchte jetzt nur noch die passenden Titeln dazu schreiben.
Meine Idee wäre das mit xsl:key zu machen, aber ich kriege das nicht hin. Hier der wesentliche Ausschnitt:
<xsl:for-each-group select="$suchwoerter" group-by="$ersterBuchstabe">
<xsl:sort select="current-grouping-key()" />
<p><h2>
<xsl:value-of select="current-grouping-key()"/>
</h2>
<p><h3>
<xsl:for-each select="current-group()">
<xsl:value-of select=".[substring(.,1,1)=current-grouping-key()]"/>
<xsl:for-each select="key('titelsuche', '.[substring(.,1,1)=current-grouping-key()]')">
<!-- Auswertung -->
</xsl:for-each>
</xsl:for-each>
</h3>
</p>
</xsl:for-each-group>
Die 2. xsl:for-each gibt den Fehler: "Cannot call the key() function when the context item is not a node". Wie kann ich den Context Item bekannt machen?
Ich weiß auch nicht, wie ich den richtigen xsl:key definieren soll. Ich dachte: <xsl:key name= "titelsuche" use="title"/> Ist es richtig? Wenn nein, was wäre richtig?
Und noch eine Frage: Soweit ich verstehe, muss xsl:key immer in obersten Ebene stehen. Ist es korrekt?
Schönen Dank im Voraus!
Julia
Hallo Julia,
habe einige Zeit gewartet, ob noch mehr Input zum Thema kommt. Wollte es aber nicht unversucht lassen. Das wäre wohl auch der algorithmische Ansatz.
Du sagst, dass $suchwoerter bereits vorab ermittelt wurde. Ich habe diese Sequenz zum Testen mit den Substantiven aus den Titeln befüllt.
Ich hoffe, etwa das ist gesucht:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="suchwoerter"
select="('Harry', 'Potter', 'Stein', 'Weisen', 'Kammer', 'Schreckens')"/>
<xsl:variable name="titel" select="//title"/>
<h1>Glossar</h1>
<xsl:for-each-group select="$suchwoerter" group-by="substring(., 1, 1)">
<xsl:sort select="current-grouping-key()" data-type="text" order="ascending"/>
<h2>
<xsl:value-of select="current-grouping-key()"/>
</h2>
<xsl:for-each select="$suchwoerter[starts-with(., current-grouping-key())]">
<xsl:sort select="." data-type="text" order="ascending"/>
<xsl:variable name="suchwort" select="."/>
<h3>
<xsl:value-of select="$suchwort"/>
</h3>
<ul>
<xsl:for-each select="$titel">
<xsl:sort select="." data-type="text" order="ascending"/>
<xsl:if test="contains(., $suchwort)">
<li>
<xsl:value-of select="."/>
</li>
</xsl:if>
</xsl:for-each>
</ul>
</xsl:for-each>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Ergebnis:
<h1>Glossar</h1>
<h2>H</h2>
<h3>Harry</h3>
<ul>
<li>Harry Potter und der Stein der Weisen</li>
<li>Harry Potter und die Kammer des Schreckens</li>
</ul>
<h2>K</h2>
<h3>Kammer</h3>
<ul>
<li>Harry Potter und die Kammer des Schreckens</li>
</ul>
<h2>P</h2>
<h3>Potter</h3>
<ul>
<li>Harry Potter und der Stein der Weisen</li>
<li>Harry Potter und die Kammer des Schreckens</li>
</ul>
<h2>S</h2>
<h3>Schreckens</h3>
<ul>
<li>Harry Potter und die Kammer des Schreckens</li>
</ul>
<h3>Stein</h3>
<ul>
<li>Harry Potter und der Stein der Weisen</li>
</ul>
<h2>W</h2>
<h3>Weisen</h3>
<ul>
<li>Harry Potter und der Stein der Weisen</li>
</ul>
Grüße,
Thomas
Hallo Julia,
"Das wäre wohl auch der algorithmische Ansatz." sollte nach "… mit den Substantiven aus den Titeln befüllt." stehen und hierzu noch als Nachtrag eine Möglichkeit zum Auslesen der Substantive aus dem bereits verwendeten $title:
<!-- … -->
<xsl:variable name="titel" select="//title"/>
<xsl:variable name="suchwoerter" select="distinct-values(for $t in $titel return tokenize($t, '\W+')[matches(substring(., 1, 1), '[A-Z]')])"/>
<!-- … -->
Im Beispiel entsteht: ('Harry', 'Potter', 'Stein', 'Weisen', 'Kammer', 'Schreckens').
Grüße,
Thomas