Eu realmente não sei XSL, mas preciso corrigir este código, eu o reduzi para torná-lo mais simples.
Estou recebendo este erro
Função XSLT / XPath inválida
nesta linha
<xsl:variable name="text" select="replace($text,'a','b')"/>
Este é o 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>
Alguém pode me dizer o que há de errado com isso?
replace()
função está disponível a partir do XPath 2.0 (e, portanto, do XSLT 2.0) e suporta substituições de expressões regulares.Respostas:
replace
não está disponível para XSLT 1.0.Codesling tem um modelo para substituição de string que você pode usar como um substituto para a função:
<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>
invocado como:
<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>
Por outro lado, se você literalmente precisar apenas substituir um caractere por outro, pode chamar o
translate
que tem uma assinatura semelhante. Algo assim deve funcionar bem:<xsl:variable name="newtext" select="translate($text,'a','b')"/>
Além disso, observe que, neste exemplo, mudei o nome da variável para "newtext", em XSLT as variáveis são imutáveis, então você não pode fazer o equivalente ao
$foo = $foo
que tinha no código original.fonte
translate
, nãoreplace
. Areplace
função no XPath 2.0 trata seu segundo argumento como uma expressão regular e substitui todas as correspondências dessa expressão pela string de substituição especificada (que pode incluir$n
referências a grupos de captura na regex). Atranslate
função (em 1.0 e 2.0) é aquela que faz substituições de caractere único por caractere único.<xsl:with-param name="replace" select="'a'" />
entre aspas em torno de a?Aqui está a função XSLT que funcionará de forma semelhante à função String.Replace () do C #.
Este modelo tem os 3 parâmetros abaixo
text : - sua string principal
substituir : - a string que você deseja substituir
por : - a string que responderá por uma nova string
Abaixo estão o modelo
<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>
O exemplo abaixo mostra como chamá-lo
<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>
Você também pode consultar o URL abaixo para obter os detalhes.
fonte
Nota: No caso de você desejar usar o algoritmo já mencionado para casos em que você precisa substituir um grande número de instâncias na string de origem (por exemplo, novas linhas em texto longo), há alta probabilidade de você acabar com
StackOverflowException
por causa da recursiva ligar.Resolvi esse problema graças à incorporação de tipo Java integrada de Xalan (não parecia como fazer no Saxon ):
<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>
fonte
Cannot find a script or an extension object associated with namespace 'xalan://java.lang.String'.
<msxsl:script>
bloco, que pode chamar qualquer método .NET, biblioteca etc. Embora o .NET também suporte as funções de extensão EXSLT, você não precisa fazer isso.Você pode usar o código a seguir quando seu processador é executado em .NET ou usa MSXML (ao contrário de processadores baseados em Java ou outros processadores nativos). Ele usa
msxsl:script
.Certifique-se de adicionar o namespace
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
à sua raizxsl:stylesheet
ouxsl:transform
elemento.Além disso, vincule
outlet
- se a qualquer namespace de sua preferência, por exemploxmlns: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')" />
fonte
prefix outlet is not defined
ou'xsl:script' cannot be a child of the 'xsl:stylesheet' element.
se mudei o msxsl pelo meu prefixo. Suponho que seja alguma magia XSLT específica da Microsoft?xsl:script
, masmsxsl:script
, e tem um namespace diferente (atualizei a resposta de John).Eu continuo acertando essa resposta. Mas nenhum deles lista a solução mais fácil para xsltproc (e provavelmente para a maioria dos processadores 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(., ' ', '')"/>
fonte
str:replace()
função. Nem qualquer um dos outros principais processadores XSLT 1.0 - Xalan, Saxon 6.5 e Microsoft.A rouina é muito boa, mas faz com que meu aplicativo trave, então precisei adicionar o caso:
<xsl:when test="$text = '' or $replace = ''or not($replace)" > <xsl:value-of select="$text" /> <!-- Prevent thsi routine from hanging --> </xsl:when>
antes que a função seja chamada recursivamente.
Eu obtive a resposta aqui: Quando o teste está suspenso em um loop infinito
Obrigado!
fonte