2010-06-18 11 views
68

Ich weiß nicht wirklich XSL, aber ich muss diesen Code beheben, ich habe es reduziert, um es einfacher zu machen.
ich diesen FehlerXSLT string ersetzen

Invalid XSLT/XPath function

auf dieser Linie

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

Diese XSL jemand

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

ist kann mir sagen, was mit ihm los?

+0

Bitte beachten Sie, dass die Funktion 'replace()' ab XPath 2.0 (und daher XSLT 2.0) verfügbar ist und den Ersatz regulärer Ausdrücke unterstützt. – Abel

Antwort

119

replace ist für XSLT 1.0 nicht verfügbar.

Codesling hat ein template for string-replace Sie als Ersatz für die Funktion verwenden können:

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

als aufgerufen:

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

Auf der anderen Seite, wenn Sie buchstäblich nur ein Zeichen ersetzen, müssen mit ein anderer, Sie können translate anrufen, die eine ähnliche Signatur hat. So etwas sollte funktionieren:

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

Beachten Sie auch, in diesem Beispiel habe ich den Variablennamen auf „newtext“ geändert, in XSLT-Variablen sind unveränderlich, so dass Sie nicht das Äquivalent von $foo = $foo wie Sie tun können hatte in Ihrem ursprünglichen Code.

+0

Danke, aber jetzt bekomme ich diesen Fehler: Eine unbekannte XPath-Erweiterungsfunktion hieß – Aximili

+0

@aximili, sorry, habe XSLT 1.0 und 2.0 verwirrt, bearbeitet ... sollte jetzt gut gehen. –

+0

Ich sehe danke Mark! – Aximili

30

Hier ist die XSLT-Funktion, die ähnlich wie die String.Replace() - Funktion von C# funktioniert.

Diese Vorlage hat die 3 Parameter wie unten

Text: - Ihre Hauptsaite

ersetzen: - die Zeichenfolge, die Sie wollen

von

ersetzt werden: - die Zeichenfolge, die mit neuer Zeichenfolge antwortet

Unten sind th e Vorlage

<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 Beispiel zeigt, wie es nennen

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

Sie können auch die below URL für die Angaben beziehen.

+0

Using xslt 1.0 Dieser Beitrag/Vorlage arbeitete für mich, während Mark Elliot's nicht. – HostMyBus

11

Hinweis: Falls Sie wünschen, die bereits erwähnte algo für Fälle verwenden, wo Sie große Anzahl von Instanzen in der Quellzeichenfolge (zB neue Linien in Langtext) ersetzen müssen es hohe Wahrscheinlichkeit Sie‘ ll enden wegen des rekursiven Aufrufs mit StackOverflowException.

Ich löste dieses Problem dank Xalan ‚s (sah nicht so aus, wie es in Saxon zu tun) Java-Typ Einbettung in eingebautem:

<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

Tut mir leid, wenn ich dumm bin, aber ich bekomme: 'Kann ein Skript oder ein Erweiterungsobjekt nicht finden, das dem Namespace 'xalan: // java.lang.String' zugeordnet ist.' –

+0

Was ist Ihre XSLT-Engine? –

+0

Die Microsoft.NET one Ich fürchte ... –

5

Sie können den folgenden Code verwenden, wenn Ihr Prozessor läuft auf .NET oder verwendet MSXML (im Gegensatz zu Java-basierten oder anderen nativen Prozessoren). Es verwendet msxsl:script.

Stellen Sie sicher, dass Sie den Namespace xmlns:msxsl="urn:schemas-microsoft-com:xslt" zu Ihrem Root-Element xsl:stylesheet oder xsl:transform hinzufügen.

Zusätzlich binden Sie outlet an einen beliebigen Namespace, zum Beispiel 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

Tut mir leid, wenn ich dumm bin, aber ich bekomme 'Präfix outlet ist nicht definiert' oder' 'xsl: script' kann kein Kind des 'xsl: stylesheet' Elements sein. Wenn ich msxsl für mein Präfix ändere. Ich vermute, das ist eine Microsoft-spezifische XSLT-Magie? –

+1

@IanGrainger, es ist nicht 'xsl: script', aber' msxsl: script', und es hat einen anderen Namensraum (Ich habe Johns Antwort aktualisiert). – Abel

0

Die rouine ist ziemlich gut, aber es ist meine App verursacht zu hängen, so brauchte ich den Fall hinzuzufügen:

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

, bevor die Funktion rekursiv aufgerufen wird.

Ich habe die Antwort von hier: When test hanging in an infinite loop

Thank you!