logo
close

Podwójne kodowanie znaków specjalnych w XSLT

14 listopada 2019
simplie Komentarze: 0 Kategoria: Aktualności

Ostatnio musiałem wyciągnąć pewne dane z pliku XML i zastosować je następnie w PHP. Ponieważ potrzebowałem zrobić to tylko raz, pomyślałem sobie że stworzę arkusz XSLT który dołączę do pliku XML. Potem otworzę plik XML w przeglądarce i skopiuję sobie wygenerowany przez arkusz XSLT kod PHP do pliku. Wydawało się to proste, więc zabrałem się do pracy i po jakimś czasie już miałem w oknie przeglądarki gotowy kod PHP. Niestety nie przewidziałem jednej rzeczy: część stringów które potrzebowałem przenieść do PHP zawierała w sobie cudzysłowy, przez co PHP zaczął się burzyć o składnię skryptu. Zatem musiałem coś z tym zrobić.

Rozwiązanie które zastosowałem opiera się na wykorzystaniu znacznika <xsl:template>. Znacznik ten można użyć na dwa sposoby: albo w celu dopasowania do określonego elementu (trzeba użyć atrybut match), lub też jako „funkcję” którą można wywołać zxa pomocą znacznika <xsl:call-template> (w tym przypadku trzeba zastosować atrybut name). Ja postanowiłem wykorzystać ten drugi sposób.

Moje rozwiązanie wykorzystuje też możliwość przekazania do takiego szablonu parametru z zewnątrz, oraz fakt że arkusz może wywołać siebie rekurencyjnie. Sam algorytm przetwarzania jest natomiast prosty:

  • jeżeli string przekazany jako parametr zawiera znak cudzysłowu, wyświetl wszystko przed cudzysłowem, następnie zakodowany podwójnie cudzysłów, i na końcu wywołaj funkcję jeszcze raz podają jako parametr to co jest po cudzysłowie;
  • jeżeli natomiast w przekazanym stringu nie ma cudzysłowu, to po prostu go wyświetl.

Gotowe rozwiązanie wygląda zatem następująco:

<xsl:template name="escaper">
    <xsl:param name="str" />
    <xsl:choose>
        <xsl:when test="contains($str, '&quot;')">
            <xsl:value-of select="substring-before($str, '&quot;')" />
            <xsl:text>&amp;quot;</xsl:text>
            <xsl:call-template name="escaper">
                <xsl:with-param name="str" select="substring-after($str, '&quot;')" />
            </xsl:call-template>
            <xsl:text></xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$str" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Samo zastosowanie powyższego kawałka kodu we własnym arkuszu XSLT jest też proste:

<xsl:template match="nazwa">
    <xsl:text>nazwy[] = &quot;</xsl:text>
    <xsl:call-template name="escaper">
        <xsl:with-param name="str" select="." />
    </xsl:call-template>
    <xsl:text>&quot;;</xsl:text>
</xsl:template>

Komentarze

Komentarz

Komentując, akceptujesz Politykę prywatności