Naprawdę nie znam XSL, ale muszę poprawić ten kod, zmniejszyłem go, aby był prostszy.
Otrzymuję ten błąd
Nieprawidłowa funkcja XSLT / XPath
w tej linii
<xsl:variable name="text" select="replace($text,'a','b')"/>
To jest plik XSL
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:inm="http://www.inmagic.com/webpublisher/query" version="1.0">
<xsl:output method="text" encoding="UTF-8" />
<xsl:preserve-space elements="*" />
<xsl:template match="text()" />
<xsl:template match="mos">
<xsl:apply-templates />
<xsl:for-each select="mosObj">
'Notes or subject'
<xsl:call-template
name="rem-html">
<xsl:with-param name="text" select="SBS_ABSTRACT" />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="rem-html">
<xsl:param name="text" />
<xsl:variable name="text" select="replace($text, 'a', 'b')" />
</xsl:template>
</xsl:stylesheet>
Czy ktoś może mi powiedzieć, co w tym złego?
replace()
funkcja jest dostępna od XPath 2.0 (a zatem XSLT 2.0) i obsługuje zastępowanie wyrażeń regularnych.Odpowiedzi:
replace
nie jest dostępny dla XSLT 1.0.Codesling ma szablon do zamiany ciągów znaków, którego możesz użyć jako substytutu dla funkcji:
<xsl:template name="string-replace-all"> <xsl:param name="text" /> <xsl:param name="replace" /> <xsl:param name="by" /> <xsl:choose> <xsl:when test="$text = '' or $replace = ''or not($replace)" > <!-- Prevent this routine from hanging --> <xsl:value-of select="$text" /> </xsl:when> <xsl:when test="contains($text, $replace)"> <xsl:value-of select="substring-before($text,$replace)" /> <xsl:value-of select="$by" /> <xsl:call-template name="string-replace-all"> <xsl:with-param name="text" select="substring-after($text,$replace)" /> <xsl:with-param name="replace" select="$replace" /> <xsl:with-param name="by" select="$by" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$text" /> </xsl:otherwise> </xsl:choose> </xsl:template>
powołany jako:
<xsl:variable name="newtext"> <xsl:call-template name="string-replace-all"> <xsl:with-param name="text" select="$text" /> <xsl:with-param name="replace" select="a" /> <xsl:with-param name="by" select="b" /> </xsl:call-template> </xsl:variable>
Z drugiej strony, jeśli potrzebujesz dosłownie tylko zamienić jeden znak na inny, możesz zadzwonić,
translate
który ma podobny podpis. Coś takiego powinno działać dobrze:<xsl:variable name="newtext" select="translate($text,'a','b')"/>
Zwróć też uwagę, że w tym przykładzie zmieniłem nazwę zmiennej na "nowy tekst", w XSLT zmienne są niezmienne, więc nie możesz zrobić odpowiednika tego
$foo = $foo
, co miałeś w oryginalnym kodzie.źródło
translate
tymreplace
.replace
Funkcja w XPath 2.0 traktuje jej jako drugi argument jest wyrażeniem regularnym i zastępuje wszystkie mecze tego wyrażenia z określonym ciągiem zastępczym (które mogą zawierać$n
odniesienia do grup przechwytywania w regex).translate
Funkcji (w 1,0 do 2,0), to taki, który ma postać pojedynczej-for-jednoznakowe wymiany.<xsl:with-param name="replace" select="'a'" />
cudzysłowów wokół a?Oto funkcja XSLT, która będzie działać podobnie do funkcji String.Replace () języka C #.
Ten szablon ma 3 parametry, jak poniżej
tekst : - twój główny ciąg
replace : - ciąg, który chcesz zamienić
by : - ciąg, który odpowie nowym napisem
Poniżej znajduje się szablon
<xsl:template name="string-replace-all"> <xsl:param name="text" /> <xsl:param name="replace" /> <xsl:param name="by" /> <xsl:choose> <xsl:when test="contains($text, $replace)"> <xsl:value-of select="substring-before($text,$replace)" /> <xsl:value-of select="$by" /> <xsl:call-template name="string-replace-all"> <xsl:with-param name="text" select="substring-after($text,$replace)" /> <xsl:with-param name="replace" select="$replace" /> <xsl:with-param name="by" select="$by" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$text" /> </xsl:otherwise> </xsl:choose> </xsl:template>
Poniższy przykład pokazuje, jak to nazwać
<xsl:variable name="myVariable "> <xsl:call-template name="string-replace-all"> <xsl:with-param name="text" select="'This is a {old} text'" /> <xsl:with-param name="replace" select="'{old}'" /> <xsl:with-param name="by" select="'New'" /> </xsl:call-template> </xsl:variable>
Aby uzyskać szczegółowe informacje, możesz również zapoznać się z poniższym adresem URL .
źródło
Uwaga: jeśli chcesz użyć wspomnianego już algo w przypadkach, w których musisz zamienić dużą liczbę wystąpień w ciągu źródłowym (np. Nowe wiersze w długim tekście), istnieje duże prawdopodobieństwo, że skończysz z
StackOverflowException
powodu rekurencyjnego połączenie.Rozwiązałem ten problem dzięki wbudowanemu osadzaniu typu Java przez Xalana (nie wyglądałem, jak to zrobić po Saksonii ):
<xsl:stylesheet version="1.0" exclude-result-prefixes="xalan str" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xalan" xmlns:str="xalan://java.lang.String" > ... <xsl:value-of select="str:replaceAll( str:new(text()), $search_string, $replace_string)"/> ... </xsl:stylesheet>
źródło
Cannot find a script or an extension object associated with namespace 'xalan://java.lang.String'.
<msxsl:script>
bloku, który może wywołać dowolną metodę .NET, bibliotekę itp. Chociaż .NET obsługuje również funkcje rozszerzenia EXSLT, więc nie musisz tego robić.Poniższego kodu można użyć, gdy procesor działa w środowisku .NET lub używa MSXML (w przeciwieństwie do procesorów opartych na języku Java lub innych natywnych). Używa
msxsl:script
.Pamiętaj, aby dodać przestrzeń nazw
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
do katalogu głównegoxsl:stylesheet
lubxsl:transform
elementu.Ponadto powiąż
outlet
na przykład z dowolną przestrzenią nazwxmlns:outlet = "http://my.functions"
.<msxsl:script implements-prefix="outlet" language="javascript"> function replace_str(str_text,str_replace,str_by) { return str_text.replace(str_replace,str_by); } </msxsl:script> <xsl:variable name="newtext" select="outlet:replace_str(string(@oldstring),'me','you')" />
źródło
prefix outlet is not defined
lub'xsl:script' cannot be a child of the 'xsl:stylesheet' element.
zmieniam msxsl na mój prefiks. Zgaduję, że to jakaś magia XSLT specyficzna dla Microsoft?xsl:script
, alemsxsl:script
i ma inną przestrzeń nazw (zaktualizowałem odpowiedź Johna).Ciągle trafiam w tę odpowiedź. Ale żaden z nich nie wymienia najłatwiejszego rozwiązania dla xsltproc (i prawdopodobnie większości procesorów XSLT 1.0):
<xsl:stylesheet version="1.0" xmlns:str="http://exslt.org/strings" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:value-of select="str:replace(., ' ', '')"/>
źródło
str:replace()
funkcji. Ani żaden z pozostałych głównych procesorów XSLT 1.0 - Xalan, Saxon 6.5 i Microsoft.Rouine jest całkiem niezły, jednak powoduje zawieszanie się mojej aplikacji, więc musiałem dodać skrzynkę:
<xsl:when test="$text = '' or $replace = ''or not($replace)" > <xsl:value-of select="$text" /> <!-- Prevent thsi routine from hanging --> </xsl:when>
zanim funkcja zostanie wywołana rekurencyjnie.
Mam stąd odpowiedź: podczas testu wisi w nieskończonej pętli
Dziękuję Ci!
źródło