可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I don\'t really know XSL but I need to fix this code, I have reduced it to make it simpler.
I am getting this error
Invalid XSLT/XPath function
on this line
<xsl:variable name=\"text\" select=\"replace($text,\'a\',\'b\')\"/>
This is the 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>
Can anyone tell me what\'s wrong with it?
回答1:
replace
isn\'t available for XSLT 1.0.
Codesling has a template for string-replace you can use as a substitute for the function:
<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>
invoked as:
<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>
On the other hand, if you literally only need to replace one character with another, you can call translate
which has a similar signature. Something like this should work fine:
<xsl:variable name=\"newtext\" select=\"translate($text,\'a\',\'b\')\"/>
Also, note, in this example, I changed the variable name to \"newtext\", in XSLT variables are immutable, so you can\'t do the equivalent of $foo = $foo
like you had in your original code.
回答2:
Here is the XSLT function which will work similar to the String.Replace() function of C#.
This template has the 3 Parameters as below
text :- your main string
replace :- the string which you want to replace
by :- the string which will reply by new string
Below are the Template
<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>
Below sample shows how to call it
<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>
You can also refer the below URL for the details.
回答3:
Note: In case you wish to use the already-mentioned algo for cases where you need to replace huge number of instances in the source string (e.g. new lines in long text) there is high probability you\'ll end up with StackOverflowException
because of the recursive call.
I resolved this issue thanks to Xalan\'s (didn\'t look how to do it in Saxon) built-in Java type embedding:
<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>
回答4:
You can use the following code when your processor runs on .NET or uses MSXML (as opposed to Java-based or other native processors). It uses msxsl:script
.
Make sure to add the namespace xmlns:msxsl=\"urn:schemas-microsoft-com:xslt\"
to your root xsl:stylesheet
or xsl:transform
element.
In addition, bind outlet
to any namespace you like, for instance xmlns: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\')\" />
回答5:
The rouine is pretty good, however it causes my app to hang, so I needed to add the case:
<xsl:when test=\"$text = \'\' or $replace = \'\'or not($replace)\" >
<xsl:value-of select=\"$text\" />
<!-- Prevent thsi routine from hanging -->
</xsl:when>
before the function gets called recursively.
I got the answer from here:
When test hanging in an infinite loop
Thank you!