2010-06-25 13 views
6

Chciałbym, aby mój wygenerowany plik wyjściowy zawierał ścieżki plików wskazujące ścieżkę względem arkusza stylów. Lokalizacja arkusza stylów może się zmienić i nie chcę używać parametru dla arkusza stylów. Moje rozwiązanie jest to, aby uzyskać pełny stylów URI:Robienie manipulacji ścieżkami plików w XSLT

<xsl:variable name="stylesheetURI" select="document-uri(document(''))" /> 

Teraz tylko trzeba odciąć od $stylesheetURI pliku. To zainspirowało mnie do napisania XSLT 2.0 klonów funkcji PHP basename i dirname:

<xsl:function name="de:basename"> 
    <xsl:param name="file"></xsl:param> 
    <xsl:sequence select="tokenize($file, '/')[last()]" /> 
</xsl:function> 

<xsl:function name="de:dirname"> 
    <xsl:param name="file"></xsl:param> 
    <xsl:sequence 
     select="string-join(tokenize($file, '/')[position() != last()], '/')" /> 
</xsl:function> 

Teraz mogę zrobić coś takiego w moim szablonu:

<img src="{concat(de:dirname($stylesheetURI),'/img/myimage,png')}" /> 

Moje pytanie brzmi: czy nie lepiej/szybsze sposoby osiągnięcia tego z natywnym XSLT 2.0?

+0

Podobało mi się praca nad tym pytaniem (+1). Zobacz moją odpowiedź, która wydaje się być o 25% szybsza. :) –

Odpowiedz

7

testowałem (nie zbyt szeroko) te funkcje i wydają się wykonać 25% szybciej niż przewidziane. Oczywiście wyniki zależą od długości struny i liczby zakwalifikowanych:

<xsl:function name="de:basename" as="xs:string"> 
    <xsl:param name="pfile" as="xs:string"/> 
    <xsl:sequence select= 
    "de:reverseStr(substring-before(de:reverseStr($pfile), '/')) 
    " /> 
    </xsl:function> 

    <xsl:function name="de:dirname" as="xs:string"> 
    <xsl:param name="pfile" as="xs:string"/> 
    <xsl:sequence select= 
    "de:reverseStr(substring-after(de:reverseStr($pfile), '/')) 
    " /> 
    </xsl:function> 

    <xsl:function name="de:reverseStr" as="xs:string"> 
    <xsl:param name="pStr" as="xs:string"/> 

    <xsl:sequence select= 
    "codepoints-to-string(reverse(string-to-codepoints($pStr)))"/> 
    </xsl:function> 
+0

Wow! Czy to możliwe, ponieważ implementacja sekwencji (z tokenizacją i łączeniem ciągów) ma więcej porowych kosztów niż manipulowanie ciągami? Ale czy ciągi do kodeków również zwracają sekwencję? –

+0

@Alejandro: tokenize() wykonuje dużo pracy - skanuje char przez char i umieszcza każdy token w osobnym elemencie. Wszędzie tam, gdzie substring-before() lub substring-after() skanuje tylko do pierwszego wystąpienia. –