2010-06-18 100 views
68

我並不十分了解XSL,但我需要修復此代碼,我已經減少了它以使其更簡單。
我收到此錯誤XSLT字符串替換

Invalid XSLT/XPath function

在這條線

<xsl:variable name="text" select="replace($text,'a','b')"/> 

這是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> 

誰能告訴我有什麼錯呢?

+0

請注意''replace()'函數可從XPath 2.0(因此XSLT 2.0)開始使用,並支持正則表達式替換。 – Abel 2015-09-24 23:55:03

回答

119

replace不適用於XSLT 1.0。

Codesling有template for string-replace可以作爲功能的替代品使用:援引爲

<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> 

<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> 

在另一方面,如果你從字面上只需要更換一個字符另一個,你可以撥打translate,它有一個類似的簽名。這樣的事情應該很好地工作:

<xsl:variable name="newtext" select="translate($text,'a','b')"/> 

此外,請注意,在這個例子中,我改變了變量名「newtext」,在XSLT變量是不變的,所以你不能這樣做的$foo = $foo相當於喜歡你在您的原始代碼。

+0

感謝馬克,但現在我得到這個錯誤: 一個未知的XPath擴展函數被調用 – Aximili 2010-06-18 04:23:59

+0

@aximili,對不起,得到XSLT 1.0和2.0困惑,編輯...應該是現在就去吧。 – 2010-06-18 04:37:54

+0

我看到謝謝馬克! – Aximili 2010-06-18 05:09:37

30

這裏是XSLT函數,其功能類似於C#的String.Replace()函數。

這個模板有3個參數如下

文本: - 你的主串

更換: - 你想要的字符串通過更換

: - 在將由新字符串回覆的字符串

下面是第Ë模板

<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> 

下面的示例演示如何調用它

<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> 

您也可以參考below URL的細節。

+0

使用xslt 1.0這篇文章/模板適用於我,而Mark Elliot沒有。 – HostMyBus 2016-09-07 09:05:22

11

注:如果你想使用在您需要替換源字符串中的情況下,數量巨大的情況下(在長文本如新線)有概率已經提到的算法中你」由於遞歸調用,最終會得到StackOverflowException

我解決了這個問題,感謝的Xalan的(不看怎麼做,在撒克遜)內置Java類型嵌入:

<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> 
+0

對不起,如果我是啞巴,但我得到:'找不到與命名空間'xalan:// java.lang.String'關聯的腳本或擴展對象。' – 2014-08-13 09:08:15

+0

什麼是您的XSLT引擎? – 2014-08-13 18:40:19

+0

微軟.NET恐怕... – 2014-08-14 08:42:53

5

您可以使用下面的代碼時您的處理器在.NET上運行或使用MSXML(而不是基於Java或其他本機處理器)。它使用msxsl:script

確保將名稱空間xmlns:msxsl="urn:schemas-microsoft-com:xslt"添加到您的根xsl:stylesheetxsl:transform元素。

另外,將outlet綁定到您喜歡的任何名稱空間,例如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')" /> 
+0

對不起,如果我愚蠢,但我得到'前綴outlet沒有定義'或''xsl:script'不能是'xsl:stylesheet'元素的子元素.'如果我更改我的前綴msxsl。我猜這是一些微軟特定的XSLT魔術? – 2014-08-13 09:02:39

+1

@IngGrainger,它不是'xsl:script',而是'msxsl:script',它有一個不同的命名空間(我已經更新了John的答案)。 – Abel 2015-09-24 23:48:36

0

的rouine是相當不錯的,但它使我的應用程序掛起,所以我需要補充的情況下:

<xsl:when test="$text = '' or $replace = ''or not($replace)" > 
    <xsl:value-of select="$text" /> 
    <!-- Prevent thsi routine from hanging --> 
    </xsl:when> 

之前的函數被遞歸調用。

我得到的答案從這裏: When test hanging in an infinite loop

謝謝!