Frage

Ich verstehe nicht, Ausgabe dieses Sheet:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates select="root/sub"/>
    </xsl:template>

    <xsl:template match="sub">
        <xsl:variable name="seq">
            <xsl:sequence select="*" />
        </xsl:variable>

        <xsl:message>
            <xsl:value-of select="@id" />
            <xsl:text>: </xsl:text>
            <xsl:value-of select="count($seq)" />
        </xsl:message>
    </xsl:template>
</xsl:stylesheet>

, wenn sie folgende XML angewendet:

<root>
    <sub id="empty" />
    <sub id="one"><one/></sub>
    <sub id="two"><one/><one/></sub>
    <sub id="three"><one/><one/><one/></sub>
</root>

Ausgabe von xsl:message Elemente geschrieben ist:

empty: 1
one: 1
two: 1
three: 1

Ich erwartete dies eine statt:

empty: 0
one: 1
two: 2
three: 3

Warum count($seq) immer wieder zurückkehren 1 in diesem Fall? Wie würden Sie Variablendefinition ändern, so dass ich es später für Leere testen kann? (Simple <xsl:variable name='seq' select='*' /> zurückkehren würde erwartete Antwort, aber ist keine Option ... Ich möchte in between Variablen ändern: diese Vorlage , und testen sie es für Leere später).

War es hilfreich?

Lösung

Lassen Sie mich versuchen, das "Warum" Teil Ihrer Frage zu beantworten.

Wenn Sie schreiben die folgende Anweisung:

<xsl:variable name="x" select="*" />

die Variable $x enthält die Reihenfolge der untergeordneten Knoten des aktuellen Knotens. Es gibt keinen impliziten Elternknoten in $x, da Sie select verwenden. Betrachten wir nun die folgenden Möglichkeiten:

<xsl:variable name="x">
    <content />
    <content />
</xsl:variable>

wobei variable $x eine Folge von einem Knoten enthält: der übergeordneten Knoten des content. Hier count($x) wird immer geben Sie 1. Um die Menge an content Elementen zu erhalten, müssen Sie die Kinder des $x impliziten Wurzelknoten zählen: count($x/content)

.

Als Faustregel kann man sich daran erinnern: , wenn xsl:variable ist selbst ein leeres Element mit einem select Attribute wird die Ergebnismenge der Variablen zugewiesen werden. Wenn Sie xsl:variable ohne select Attribut verwenden, können Sie immer einen impliziten Elternteil mit den Variablen erstellen, und der Inhalt der Variablen sind die Kinder darunter .

Das gleiche gilt für Ihr Beispiel mit xsl:sequence als Kind xsl:variable. Dadurch, dass ein nicht-leeres xsl:variable Sie ein implizit Eltern für die Sequenz erstellen, weshalb man immer 1, wenn Sie die Variable selbst zählen.

Wenn Sie beide benötigen: ein Bündel von Anweisungen innerhalb xsl:variable, aber das Verhalten des select Attribut können Sie diese Abhilfe, indem Sie wie folgt vor:

<xsl:variable name="x" select="$y/*" />

<xsl:variable name="y">
    <xsl:sequence select="foo" />
</xsl:variable>

, welche nun die erwartete Menge für count($x) ergeben, aber ob diese wirklich von Vorteil ist oder macht den Code klarer diskutierbar ist.

Andere Tipps

Es funktioniert wie man es erwarten könnte, wenn Sie entweder die Variablendeklaration ändern:

<xsl:variable name="seq" select="*"/>

oder die Art der Variablen deklarieren Verwendung ‚als‘ Attribut:

<xsl:variable name="seq" as="item()*">
        <xsl:sequence select="*" />
</xsl:variable>

Nicht jede Art Informationen oft leeds zu überraschenden Ergebnissen in XSLT 2.0 spezifiziert. Wenn Sie Saxon verwenden, können Sie die Ausgabe wie Saxon interpretiert das Stylesheet das erklären Erweiterung Attribut:

    <xsl:template match="sub" saxon:explain="yes" xmlns:saxon="http://saxon.sf.net/">
    <xsl:variable name="seq">
        <xsl:sequence select="*" />
    </xsl:variable>

    <xsl:message>
        <xsl:value-of select="@id" />
        <xsl:text>: </xsl:text>
        <xsl:value-of select="count($seq)" />
    </xsl:message>
</xsl:template>

Wie Sie sehen können, Saxon konstruiert ein Dokument-Knoten aus der Folge:

Optimized expression tree for template at line 6 in :
                    let $seq[refCount=1] as document-node() :=
                      document-constructor
                        child::element()
                    return
                      message

Sie sind die Auswahl der Unterknoten, und dann jeden Knoten zu zählen - so dass es dann immer 1. Sie müssen die Kinder zählen, zum Beispiel:

<xsl:value-of select="count($seq/*)" />

geben Sie die Ausgabe Sie erwarten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top