2010-01-30 13 views
10

Czy jest możliwe przekazanie zmiennej z jednego szablonu nadrzędnego do jej elementu potomnego?XSL: przekazywanie zmiennych między szablonami

<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> 

ten szablon będzie pasował:

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

Widzisz chcę użycia var jako var1 w dopasowanej matrycy.

Jak mogę to ułatwić?

edit: struktura jest tak:

<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> 

w funkcji JScript ciąg jest bez ukośników. ktoś wie dlaczego?

C: xampplitehtdocsxamppimg

+0

To powinno "po prostu działać" - pytanie sugeruje, że tak nie jest. Nie czekaj ... nazwa szablonu i select = nie pasują do pokazanego kodu, masz select = "folders" i match = "folder" bez "s". Czy to jest problem, czy jest to tylko przykład? – Murph

+0

Sprawdź moją odpowiedź tutaj http://stackoverflow.com/a/41530702/4251431 –

Odpowiedz

26

można przekazać parametry do nazwanych szablonów nazywasz poprzez <xsl:call-template>, np .:

<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> 

Kiedy zadzwonisz nazwie szablonu, węzeł kontekstu jest obecny kontekst. Tak nazwać imieniem szablon dla węzłów podrzędnych, trzeba zmienić bieżący kontekst za pomocą <xsl:for-each>:

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

W twoim przypadku jednak, że nie ma potrzeby, aby przekazać parametry, od zmiennej że starasz się użycie jest czymś, do czego można nawigować z węzła kontekstu.I nie trzeba użyć wszystkich tych zmiennych (nie należy nigdy nadać nazwę zmiennej jako bezużyteczny jak var1):

<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> 

Również byłbym skłonny do korzystania ancestor::structure[1]/@path zamiast ../../@path, bo czyni zamiar dużo bardziej wyraźnym; twoja wersja oznacza "pobierz atrybut path z elementu nadrzędnego elementu nadrzędnego", podczas gdy moja wersja oznacza "przechodź przez łańcuch elementów-przodków, dopóki nie znajdziesz pierwszego o nazwie structure i uzyskaj jego atrybut path."

+2

+1 za doradzanie idiomatycznego sposobu wykonania tego (np. za pomocą kontekstu zamiast zmiennych). (BTW: Backslashes w twojej odpowiedzi muszą zostać naprawione.) – Tomalak

+0

No dobra. JavaScript. Naprawiony. –

+0

Nie, wciąż nie jest całkowicie naprawiony. Żadne ukośniki nie są dozwolone w XPath (patrz ostatni akapit). – Tomalak

5

Dwa problemy z szablonem structure:

  1. Aplikujesz szablony wybranie folders, ale mają dopasowanie szablonu na folder. Zmień go na folder lub jeśli masz szablon folders, upewnij się, że przekazuje on wartość parametru var1 do szablonu folder.
  2. Twoja funkcja z-param @ select używa '{var}', która wybiera literalny ciąg {var}. Jeśli chcesz wybrać zmienną var, usuń otaczające cytaty i nawiasy klamrowe i po prostu wybierz $var.

Zastosowane zmiany w szablonie structure:

<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

Dokładny kod dla wywołania byłoby:

<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> 

Innym sposobem dostępu do atrybut @path węzła głównego byłoby modyfikowanie szablonu do:

<xsl:template match="folder"> 
    <xsl:value-of select="../../../@path"/> 
</xsl:template> 
+0

ostatnia propozycja działa dobrze dla mnie. thx – binaryguy

7

Przy użyciu XSLT 2.0, to jest można przekazać parametry do szablonów podrzędnych, dodając tunnel="yes" do <xsl:with-param .../> na callsite oraz elementu </xsl:with-param .../> w nazwie szablonu, jak również. Wystarczy zrobić:

<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> 

W celu uzyskania dalszych informacji, proszę zapoznać się z sekcją 10.1.2 Tunnel parameters w specyfikacji XSLT 2.0.


Rozszerzony przykład

Z parametrów tunelu, nawet można to zrobić:

<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> 

Ponieważ atrybutu tunelu, parametr var1 przechodzi z początkowego szablonu przez wszystkich szablonów pośrednich do szablonu "folder/date".

Wystarczy pamiętać, że deklaracja atrybutu tunnel="yes" muszą być obecne zarówno na odpowiednim atrybutem <xsl:with-param name="var1" tunnel="yes" select="..."/> na <xsl:param name="var1" tunnel="yes"/>I.

Powiązane problemy