2010-01-30 11 views
10

Kann eine Variable von einer übergeordneten Vorlage an ihr untergeordnetes Element übergeben werden?XSL: Variablen zwischen Vorlagen übergeben

<xsl:template match="structure"> 
    <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable> 
    <xsl:apply-templates select="folders"> 
    <xsl:with-param name="var1" select="'{var}'"/> 
    </xsl:apply-templates> 
</xsl:template> 

wird diese Vorlage entsprechen:

<xsl:template match="folder"> 
    <xsl:param name="var1"/> 
    <xsl:value-of select="$var1"/> 
</xsl:template> 

Sie sehen, ich Verwendung var als var1 in der angepassten Vorlage will.

Wie kann ich das schaffen?

edit: die Struktur ist wie folgt:

<structure path="C:\xampplite\htdocs\xampp"> 
    <folders> 
    <folder name="img"> 
     <date>01/28/10 21:59:00</date> 
     <size>37.4 KB</size> 
    </folder> 
</folders> 
</structure> 

edit2:

<xsl:template match="folder"> 
<xsl:variable name="var1"><xsl:value-of select="../../@path"/></xsl:variable> 
<xsl:variable name="var2"><xsl:value-of select="@name" /></xsl:variable> 
<xsl:variable name="var3"><xsl:value-of select="$var1"/>\<xsl:copy-of select="$var2"/> </xsl:variable> 
<th colspan="2" align="left" bgcolor="#FF5500"><a onclick="foo('{$var3}')"><xsl:value-of select="$var3"/></a></th> 

in der JScript-Funktion die Zeichenfolge ohne seine Schrägstriche ist. weiß jemand warum?

C: xampplitehtdocsxamppimg

+0

Das sollte "einfach funktionieren" - die Frage impliziert, ist es nicht. Nein warte ... der Vorlagenname und die Auswahl = stimmen nicht mit dem angezeigten Code überein, du hast select = "Ordner" und match = "Ordner" ohne 's'. Ist das das Problem oder ist das nur ein Beispiel? – Murph

+0

check out meine Antwort hier http://StackOverflow.com/A/41530702/4251431 –

Antwort

26

Sie Parameter benannten Vorlagen passieren können, die Sie über <xsl:call-template> nennen, z.B .:

<xsl:call-template name="name"> 
    <xsl:with-param name="param" select="xpathexpr"/> 
</xsl:call-template> 

<xsl:template name="name"> 
    <xsl:param name="param"/> 
    ... 
</xsl:template> 

Wenn Sie eine benannte Vorlage nennen, der Kontextknoten ist der aktuelle Kontext. So eine benannte Vorlage rufen Sie für untergeordnete Knoten, müssen Sie den aktuellen Kontext ändern <xsl:for-each> unter Verwendung:

<xsl:for-each select="child"> 
    <xsl:call-template name="name"> 
     <xsl:with-param name="param" select="xpathexpr"/> 
    </xsl:call-template> 
</xsl:for-each> 

In Ihrem Fall, aber es gibt keine Notwendigkeit Parameter zu übergeben, da die Variable, die Sie versuchen zu Verwendung ist etwas, zu dem vom Context-Knoten aus navigierbar ist.Und Sie nicht alle diese Variablen verwenden müssen (noch sollten Sie immer eine Variable einen Namen als nutzlos wie var1 geben):

<xsl:template match="folder"> 
    <xsl:variable name="linkarg" value="concat(../../@path, '\\', @name)"/> 
    <xsl:variable name="linktext" value="concat(../../@path, '\', @name)"/> 
    <th colspan="2" align="left" bgcolor="#FF5500"> 
     <a onclick="foo('{$linkarg}')"> 
     <xsl:value-of select="$linktext"/> 
     </a> 
    </th> 
</xsl:template> 

Auch würde ich versucht sein ancestor::structure[1]/@path zu verwenden, anstatt ../../@path, weil es macht die Absicht viel expliziter; Ihre Version bedeutet "Holen Sie sich das path Attribut aus dem Elternelement des Elternelements", während meine Version bedeutet "durchlaufen Sie die Kette der Vorfahren Elemente, bis Sie die erste namens structure finden, und erhalten Sie die path Attribut."

+2

+1 für die Beratung der idiomatischen Art und Weise zu tun (z. B. mit Kontext statt Variablen). (BTW: Die Backslashes in Ihrer Antwort müssen behoben werden.) – Tomalak

+0

Oh, richtig. JavaScript. Fest. –

+0

Nein, immer noch nicht vollständig behoben. In XPath sind keine Backslashes erlaubt (siehe letzten Absatz). – Tomalak

5

Zwei Probleme mit der structure Vorlage:

  1. Sie bewerben Vorlagen Auswahl folders, haben aber ein Template-Matching auf folder. Ändern Sie es entweder in folder, oder wenn Sie eine folders Vorlage haben, stellen Sie sicher, dass sie den var1 Parameterwert an die folder Vorlage übergibt.
  2. Ihr with-param @select verwendet '{var}', der diese literale Zeichenfolge {var} auswählt. Wenn Sie die Variable var auswählen möchten, entfernen Sie die umgebenden Anführungszeichen und geschweiften Klammern und wählen Sie einfach $var.

Angewandte Änderungen an Ihrer structure Vorlage:

<xsl:template match="structure"> 
    <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable> 
    <xsl:apply-templates select="folder"> 
    <xsl:with-param name="var1" select="$var"/> 
    </xsl:apply-templates> 
</xsl:template> 
4

Der genaue Code für den Aufruf wäre:

<xsl:template match="structure"> 
    <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable> 
    <xsl:apply-templates select="folders/folder"> 
    <xsl:with-param name="var1" select="$var"/> 
    </xsl:apply-templates> 
</xsl:template> 

andere Möglichkeit, die @path Attribut des Root-Knotens zuzugreifen wäre Ändern Sie Ihre Vorlage zu:

+0

der letzte Vorschlag funktioniert gut für mich. thx – binaryguy

7

Wenn XSLT 2.0 verwenden, es ist möglich Parameter Kind Vorlagen passiert, durch tunnel="yes" zum <xsl:with-param .../> am callsite Zugabe und zum </xsl:with-param .../> Elemente an der auch genannt Vorlage. Just do:

<xsl:template match="folder"> 
    <xsl:param name="var1" tunnel="yes"/> <!-- note the 'tunnel="yes"' attribute here! --> 
    <xsl:value-of select="$var1"/> 
</xsl:template> 

<xsl:template match="structure"> 
    <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable> 
    <xsl:apply-templates select="folders"> 
    <xsl:with-param name="var1" select="$var" tunnel="yes"/> <!-- note the 'tunnel' attribute here, too! --> 
    </xsl:apply-templates> 
</xsl:template> 

Weitere Informationen entnehmen Sie bitte den Abschnitt 10.1.2 Tunnel parameters in der XSLT-2.0-Spezifikation.


Ein erweitertes Beispiel

Mit Tunnelparameter könnten Sie auch dies tun:

<xsl:template match="structure"> 
    <!-- same as before --> 
</xsl:template> 

<xsl:template match="folder"> 
    <!-- Look, ma, no param declaration! --> 
    <!-- ... --> 
    <xsl:apply-templates select="date"/> 
    <!-- ... --> 
</xsl:template> 

<xsl:template match="folder/date"> 
    <xsl:param name="var1" tunnel="yes"/> 
    <xsl:value-of select="$var1"/> 
</xsl:template> 

Wegen des Tunnel Attribut wird der var1 Parameter von der anfänglichen Vorlage durch alle Zwischenschablonen übergeben in die "folder/date" Vorlage.

Denken Sie daran, dass die tunnel="yes" Attributdeklaration sowohl auf der <xsl:param name="var1" tunnel="yes"/>UND dem entsprechenden <xsl:with-param name="var1" tunnel="yes" select="..."/> Attribut vorhanden sein muss.

Verwandte Themen