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, '"')"> <xsl:value-of select="substring-before($str, '"')" /> <xsl:text>&quot;</xsl:text> <xsl:call-template name="escaper"> <xsl:with-param name="str" select="substring-after($str, '"')" /> </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[] = "</xsl:text> <xsl:call-template name="escaper"> <xsl:with-param name="str" select="." /> </xsl:call-template> <xsl:text>";</xsl:text> </xsl:template>
Komentarze