xsl:sort und descendant-or-self
Elmex
- xsl
Hallo! Ich poste hier nochmal eine Frage von mir, die schon im Arschiv gelandet war:
Frage:
Mein Problem ist folgendes:
ich habe viele ineinander verschachtelte <page> (für ein Menü).
diese will ich jetzt nach priorität sortiert ausgeben.
dazu benutze ich
<xsl:apply-templates select="Page">
<xsl:sort data-type="number" order="ascending" select="@priority"/>
</xsl:apply-templates>
die ausgabe erfolgt jetzt auch in der richtigen reihenfolge.
In dem Template möchte ich jetzt die id einer <page> ausgeben, wenn es sie gibt, ansonsten die von der ersten untergeordneten page (die oberste seite mit inhalt):
<xsl:value-of select="descendant-or-self::Page/@id"/>
Hierbei funktioniert die sortierung nicht, da die untergeordnete ebene ja noch nicht soritert ist. Gibt es eine Möglichkeit, die unteren ebenen vorher zu sortieren?
Grüße, Elmex
Antwort1:
Die folgende Nachricht zum Thema stammt von: Thomas J.S., 17. 02. 2005, 00:16
Hallo,
In dem Template möchte ich jetzt die id einer <page> ausgeben, wenn es sie gibt, ansonsten die von der ersten untergeordneten page (die oberste seite mit inhalt):
<xsl:value-of select="descendant-or-self::Page/@id"/>
Hierbei funktioniert die sortierung nicht, da die untergeordnete ebene ja noch nicht soritert ist.
Die Sortierung bezieht sich auf die Ausgabe und nicht auf das XML an sich selbst. D.h. in deinem Fall, dass die <Page>-Elemente in der gegebenen Reihenfolge (@priority) bei der Transformation abgearbeitet werden.
Gibt es eine Möglichkeit, die unteren ebenen vorher zu sortieren?
Das kommt darauf an, wonach du sortieren möchtest.
Was meinst du mit "ersten untergeordneten page"? Wonach ist dieser "page" die erste? In der Ausgabe oder im XML-Quelltext?
Grüße
Thomas
neue Antwort:
Die XML sieht folgend aus:
<PageHierarchy>
<Page priority="100" name="Niederlassungen">
<Page priority="20" name="Deutschland">
<Page name="Osnabrück" id="1" priority="10"/>
<Page name="Hamburg" id="2" priority="20"/>
<Page name="Bremen" id="3" priority="30"/>
<Page name="Hannover" id="4" priority="40"/>
</Page>
<Page name="Niederlande" priority="10">
<Page name="Enschede" id=8"" priority="10"/>
</Page>
</Page>
</PageHierarchy>
Daraus soll ein Menü erstellt werden. Die Pages sind im XML aber nicht in der richtigen Reihenfolge (@priority). Deshalb sortiere ich sie bei aufruf des templates mit xml:sort.
Dies funktioniert bei der Darstellung der Menüpunkte auch.
Das Problem ist, dass nicht alle Seiten Inhalt haben, sondern nur die, die eine ID besizten. Bei Seiten ohne ID soll die erste-Kindseite angezeigt werden, sortiert nach priority.
<xsl:value-of select="descendant-or-self::Page/@id"/> liefert mit aber die Kindseite, wie sie im XML steht (Bei klick auf "Niederlassungen" also "Osnabrück" statt "Enschede").
Hallo,
Ich komme erst jetzt dazu zu antworten:
Die XML sieht folgend aus:
<PageHierarchy>
<Page priority="100" name="Niederlassungen">
<Page priority="20" name="Deutschland">
<Page name="Osnabrück" id="1" priority="10"/>
<Page name="Hamburg" id="2" priority="20"/>
<Page name="Bremen" id="3" priority="30"/>
<Page name="Hannover" id="4" priority="40"/>
</Page>
<Page name="Niederlande" priority="10">
<Page name="Enschede" id=8"" priority="10"/>
</Page>
</Page>
</PageHierarchy>Daraus soll ein Menü erstellt werden. Die Pages sind im XML aber nicht in der richtigen Reihenfolge (@priority). Deshalb sortiere ich sie bei aufruf des templates mit xml:sort.
Dies funktioniert bei der Darstellung der Menüpunkte auch.
Das Problem ist, dass nicht alle Seiten Inhalt haben, sondern nur die, die eine ID besizten. Bei Seiten ohne ID soll die erste-Kindseite angezeigt werden, sortiert nach priority.
<xsl:value-of select="descendant-or-self::Page/@id"/> liefert mit aber die Kindseite, wie sie im XML steht (Bei klick auf "Niederlassungen" also "Osnabrück" statt "Enschede").
<xsl:template match="PageHierarchy">
xsl:apply-templates
<xsl:sort select="@priority" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Page[not(@id)]">
<xsl:value-of select="@name" />
<br />
xsl:apply-templates
<xsl:sort select="@priority" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Page[@id]">
<xsl:value-of select="@name" />
<br />
</xsl:template>
Grüße
Thomas
<xsl:template match="PageHierarchy">
xsl:apply-templates
<xsl:sort select="@priority" />
</xsl:apply-templates>
</xsl:template><xsl:template match="Page[not(@id)]">
<xsl:value-of select="@name" />
<br />
xsl:apply-templates
<xsl:sort select="@priority" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Page[@id]">
<xsl:value-of select="@name" />
<br />
</xsl:template>Grüße
Thomas
Wenn ich hiermit die ID mit ausgebe, bekomme ich leider weiterhin die falsche id.
<xsl:template match="Page[not(@id)]">
<xsl:value-of select="concat(@name,' ',descendant-or-self::Page/@id)"/>
<br/>
xsl:apply-templates
<xsl:sort select="@priority"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Page[@id]">
<xsl:value-of select="concat(@name,' ',@id)"/>
<br/>
</xsl:template>
Ergebnis:
Niederlassungen 1
Niederlande 8
Enschede 8
Deutschland 1
Osnabrück 1
Hamburg 2
Bremen 3
Hannover 4
Bei "niederlassungen" brauche ich aber die ID 8 für "Enschede".
Grüße, Elmex
Hallo,
Wenn ich hiermit die ID mit ausgebe, bekomme ich leider weiterhin die falsche id.
<xsl:template match="Page[not(@id)]">
<xsl:value-of select="concat(@name,' ',descendant-or-self::Page/@id)"/>
Wenn du nachdenkst, siehst du selbst das das relativ unsinnig ist:
-or-self greift so oder so nicht, da das Template Pages ohne id abarbeitet.
descendat liefert deshalb die falsch ID, weil es Pages im document-order (also so wie sie im Quelltext stehen) durchsucht und davon das erste treffende nimmt.
Ergebnis:
Niederlassungen 1
Bei "niederlassungen" brauche ich aber die ID 8 für "Enschede".
Folgendes sollte dir das Gewüschte ausgeben:
<xsl:template match="PageHierarchy">
<xsl:for-each select="Page[not(@id) and Page[not(@id)]]">
<xsl:sort select="@priority" />
<xsl:variable name="subpageid">
<xsl:for-each select="Page[not(@id)]">
<xsl:sort select="@priority" />
<xsl:if test="position()= 1">
<xsl:for-each select="Page[@id]">
<xsl:sort select="@priority" />
<xsl:if test="position()= 1">
<xsl:value-of select="@id" />
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<div>
<xsl:value-of select="concat(@name, ' ', $subpageid)"/>
xsl:apply-templates
<xsl:sort select="@priority" />
</xsl:apply-templates>
</div>
<br />
</xsl:for-each>
</xsl:template>
<xsl:template match="Page[not(@id) and Page[@id]]">
<xsl:variable name="subpageid">
<xsl:for-each select="Page[@id]">
<xsl:sort select="@priority" />
<xsl:if test="position()= 1">
<xsl:value-of select="@id" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<div style="text-indent:25px;">
<xsl:value-of select="concat(@name, ' ', $subpageid)"/>
xsl:apply-templates
<xsl:sort select="@priority" />
</xsl:apply-templates>
</div>
</xsl:template>
<xsl:template match="Page[@id]">
<div style="text-indent:50px;">
<xsl:value-of select="concat(@name,' ',@id)"/>
</div>
</xsl:template>
Grüße
Thomas