Realmente no sé XSL pero necesito arreglar este código, lo he reducido para hacerlo más simple.
Estoy recibiendo este error
Función XSLT / XPath no válida
en esta linea
<xsl:variable name="text" select="replace($text,'a','b')"/>
Este es el 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>
¿Alguien puede decirme qué tiene de malo?
replace()
función está disponible desde XPath 2.0 (y por lo tanto XSLT 2.0) en adelante y admite reemplazos de expresiones regulares.Respuestas:
replace
no está disponible para XSLT 1.0.Codesling tiene una plantilla para reemplazar cadenas que puede usar como sustituto de la función:
<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 otro lado, si literalmente solo necesita reemplazar un carácter por otro, puede llamar al
translate
que tenga una firma similar. Algo como esto debería funcionar bien:<xsl:variable name="newtext" select="translate($text,'a','b')"/>
Además, tenga en cuenta que en este ejemplo, cambié el nombre de la variable a "nuevo texto", en XSLT las variables son inmutables, por lo que no puede hacer el equivalente
$foo = $foo
a lo que tenía en su código original.fuente
translate
, noreplace
. Lareplace
función en XPath 2.0 trata su segundo argumento como una expresión regular y reemplaza todas las coincidencias de esa expresión con la cadena de reemplazo especificada (que puede incluir$n
referencias a la captura de grupos en la expresión regular). Latranslate
función (en 1.0 y 2.0) es la que hace reemplazos de un solo carácter por un solo carácter.<xsl:with-param name="replace" select="'a'" />
con comillas alrededor de la a?Aquí está la función XSLT que funcionará de manera similar a la función String.Replace () de C #.
Esta plantilla tiene los 3 parámetros de la siguiente manera
texto : - tu cadena principal
reemplazar : - la cadena que desea reemplazar
por : - la cadena que responderá con una nueva cadena
A continuación se muestra la plantilla
<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>
El siguiente ejemplo muestra cómo llamarlo
<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>
También puede consultar la siguiente URL para obtener más detalles.
fuente
Nota: En caso de que desee utilizar el algoritmo ya mencionado para los casos en los que necesite reemplazar una gran cantidad de instancias en la cadena de origen (por ejemplo, nuevas líneas en texto largo), existe una alta probabilidad de que termine
StackOverflowException
debido al recursivo llamada.Resolví este problema gracias a la incrustación de tipo Java incorporada de Xalan (no vi cómo hacerlo en 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>
fuente
Cannot find a script or an extension object associated with namespace 'xalan://java.lang.String'.
<msxsl:script>
bloque, que puede llamar a cualquier método .NET, biblioteca, etc. Aunque .NET también admite las funciones de extensión EXSLT, por lo que no es necesario.Puede usar el siguiente código cuando su procesador se ejecuta en .NET o usa MSXML (a diferencia de los procesadores nativos basados en Java u otros). Utiliza
msxsl:script
.Asegúrese de agregar el espacio
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
de nombres a su raízxsl:stylesheet
oxsl:transform
elemento.Además, vincula
outlet
a cualquier espacio de nombres que quieras, por ejemploxmlns: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')" />
fuente
prefix outlet is not defined
o'xsl:script' cannot be a child of the 'xsl:stylesheet' element.
si cambio msxsl por mi prefijo. Supongo que esto es algo de magia XSLT específica de Microsoft.xsl:script
, peromsxsl:script
, y tiene un espacio de nombres diferente (he actualizado la respuesta de John).Sigo dando esta respuesta. Pero ninguno de ellos enumera la solución más sencilla para xsltproc (y probablemente la mayoría de los procesadores 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(., ' ', '')"/>
fuente
str:replace()
función. Tampoco lo hace ninguno de los otros procesadores XSLT 1.0 principales: Xalan, Saxon 6.5 y Microsoft.La rutina es bastante buena, sin embargo, hace que mi aplicación se cuelgue, por lo que necesitaba agregar el caso:
<xsl:when test="$text = '' or $replace = ''or not($replace)" > <xsl:value-of select="$text" /> <!-- Prevent thsi routine from hanging --> </xsl:when>
antes de que la función se llame de forma recursiva.
Obtuve la respuesta desde aquí: cuando la prueba se cuelga en un bucle infinito
¡Gracias!
fuente