2012-01-31 5 views
6

chcę użyć atrybutu @sourcename w następujący sposób, jako udogodnienie:XSLT: przypisanie zmienne równe jednemu z dwóch przypadkach

Jeśli @sourcename ma kropkę w nim, część przed pierwszą kropką należy przypisać do $srcgroup, a część po pierwszej kropce powinna być przypisana do $srcword.

W przeciwnym razie $srcgroup powinno być ustawione na równe @sourcename, a $srcword powinno być pustym ciągiem.

W obu przypadkach chcę zrobić to samo, używając $srcgroup i $srcword.

Próbowałem to z następującego fragmentu:

<xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')">  
    <xsl:variable name="srcgroup" select="substring-before(@sourcename, '.')"/> 
    <xsl:variable name="srcword" select="substring-after(@sourcename, '.')" /> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:variable name="srcgroup" select="@sourcename" /> 
    <xsl:variable name="srcword" />      
    </xsl:otherwise> 
</xsl:choose> 

<foo group="{$srcgroup}" word="{$srcword}" /> 
<!-- there's some other more complicated users of $srcgroup and $srcword --> 

Problem polega na tym, że pojawia się błąd (to jest przy użyciu JAXP w Javie):

ERROR: [my xsl file]: line 35: Variable or parameter 'srcgroup' is undefined.' 
FATAL ERROR: 'Could not compile stylesheet' 
Exception in thread "main" javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet 
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:825) 

Jeśli dobrze rozumiem to prawo, I” Zgaduję, że zmienne mają tylko zakres konkretnego przypadku w bloku <xsl:choose>. Czy istnieje sposób na obejście tego? Nie chcę powtarzać drugiego kodu dwukrotnie.


p.s. Znalazłem obejście:

<xsl:variable name="srcgroup" select="substring-before(concat(@sourcename, '.'), '.')" /> 
<xsl:variable name="srcword" select="substring-after(@sourcename, '.')" /> 

, ale nadal chcę wiedzieć, jak rozwiązać moje oryginalne pytanie, na przyszłość.

Odpowiedz

5

Wystarczy użyć (nie warunkowe konieczne):

<xsl:variable name="srcgroup" select= 
    "substring-before(concat(@sourcename, '.'), '.')"/> 

    <xsl:variable name="srcword" select= 
    "substring-after(@sourcename, '.')"/> 

kompletny przykład:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="x|y"> 
    <xsl:variable name="srcgroup" select= 
    "substring-before(concat(@sourcename, '.'), '.')"/> 

    <xsl:variable name="srcword" select= 
    "substring-after(@sourcename, '.')"/> 

    $srcgroup = "<xsl:value-of select="$srcgroup"/>" 
    $srcword = "<xsl:value-of select="$srcword"/>" 
</xsl:template> 
</xsl:stylesheet> 

po nałożeniu tego dokumentu XML:

<t> 
    <x sourcename="a.b.c"/> 
    <y sourcename="noDots"/> 
</t> 

poszukiwanych wynik jest produkowany w obu przypadkach:

$srcgroup = "a" 
    $srcword = "b.c" 

    $srcgroup = "noDots" 
    $srcword = "" 

Objaśnienie: Niepotrzebne logikę uniknąć poprzez umieszczenie wartowniczy.


Porównaj to do znacznie bardziej gadatliwy warunkowy składni:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="x|y"> 
    <xsl:variable name="srcgroup"> 
    <xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')"> 
     <xsl:value-of select="substring-before(@sourcename, '.')"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="@sourcename"/> 
    </xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <xsl:variable name="srcword"> 
    <xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')"> 
     <xsl:value-of select="substring-after(@sourcename, '.')"/> 
    </xsl:when> 
    <xsl:otherwise/> 
    </xsl:choose> 
    </xsl:variable> 

    $srcgroup = "<xsl:value-of select="$srcgroup"/>" 
    $srcword = "<xsl:value-of select="$srcword"/>" 
</xsl:template> 
</xsl:stylesheet> 

Kiedy to bardziej gadatliwy transformacji jest stosowane w dokumencie samo XML (powyżej), to samo jeszcze raz poprawny wynik jest produkowany:

$srcgroup = "a" 
    $srcword = "b.c" 

    $srcgroup = "noDots" 
    $srcword = "" 
+0

Jeśli przeczytasz mój komentarz na końcu mojego posta, zobaczysz, że to wymyśliłem ... to jest pomocne w obsłudze tego konkretnego przypadku, ale nie odpowiada mi na pytanie, jak warunkowo przypisać zmienną. –

+0

Nawiasem mówiąc, masz błąd - nie powinieneś używać concata w przypadku 'substring-after', ponieważ tworzy on dodatkową kropkę na końcu' srcword' w niepustym przypadku. –

+0

@JasonS: Poprawiłem moją odpowiedź. I tak, dokładnie odpowiada na pytanie, jak warunkowo zdefiniować zmienną. Jak widać, żadne warunki nie są konieczne do zdefiniowania zmiennych w pożądany sposób. –

5

To więcej tak:

<xsl:variable name="srcgroup"> 
<xsl:choose...> 
    ... 
</xsl:choose> 
</xsl:variable> 
+0

+1, ale czy możesz mi pomóc ze składnią? Nie wiem, jak używać '' bez 'select =' –

+0

Zawartość tagu jest wartością zmiennej. Wpisz '', w którym chcesz umieścić zadanie w ''. –

+0

Zobacz też - http://www.w3.org/TR/xslt - w razie wątpliwości naprawdę pomocne źródło informacji. –

Powiązane problemy