Ist xsl: Sequenz immer nicht leer?
-
11-09-2019 - |
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).
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.