2010-06-18 32 views
68

Tôi không thực sự biết XSL nhưng tôi cần phải sửa mã này, tôi đã giảm nó để làm cho nó đơn giản hơn.
Tôi nhận được lỗi nàyXSLT chuỗi thay thế

Invalid XSLT/XPath function

trên dòng này

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

Đây là 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> 

bất cứ ai có thể cho tôi biết những gì xảy ra với nó?

+0

Xin lưu ý rằng hàm 'replace()' có sẵn từ XPath 2.0 (và do đó XSLT 2.0) trở đi và hỗ trợ các thay thế biểu thức chính quy. – Abel

Trả lời

119

replace không khả dụng cho XSLT 1.0.

Codesling có template for string-replace bạn có thể sử dụng như là một thay thế cho chức năng:

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

gọi như:

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

Mặt khác, nếu bạn có nghĩa là chỉ cần thay thế một nhân vật với người khác, bạn có thể gọi số translate có chữ ký tương tự. Một cái gì đó như thế này sẽ làm việc tốt:

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

Ngoài ra, lưu ý, trong ví dụ này, tôi đã thay đổi tên biến để "newtext", trong các biến XSLT là không thay đổi, vì vậy bạn không thể làm tương đương với $foo = $foo như bạn đã có trong mã ban đầu của bạn.

+0

Cảm ơn Mark, nhưng bây giờ tôi nhận được lỗi này: Một chức năng mở rộng XPath không xác định được gọi là – Aximili

+0

@aximili, xin lỗi, có XSLT 1.0 và 2.0 bị nhầm lẫn, chỉnh sửa ... nên được tốt để đi ngay bây giờ. –

+0

Tôi thấy cảm ơn Mark! – Aximili

30

Đây là hàm XSLT sẽ hoạt động tương tự như hàm String.Replace() của C#.

mẫu này có 3 thông số như sau

văn bản: - chuỗi chính của bạn

thay: - chuỗi mà bạn muốn thay thế

bởi: - các chuỗi sẽ trả lời bằng chuỗi mới

Dưới đây là e 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> 

Dưới mẫu cho thấy làm thế nào để gọi nó là

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

Bạn cũng có thể tham khảo các below URL cho các chi tiết.

+0

Sử dụng xslt 1.0 Bài đăng/mẫu này làm việc cho tôi trong khi Mark Elliot thì không. – HostMyBus

11

Lưu ý: Trong trường hợp bạn muốn sử dụng algo đã nói cho trường hợp bạn cần phải thay thế số lượng lớn các trường hợp trong chuỗi nguồn (ví dụ dòng mới trong văn bản dài) có cao khả năng bạn' sẽ kết thúc với StackOverflowException vì cuộc gọi đệ quy.

tôi giải quyết vấn đề này nhờ Xalan 's (không nhìn làm thế nào để làm điều đó trong Saxon) built-in Java kiểu nhúng:

<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

Xin lỗi nếu tôi câm nhưng tôi nhận được: 'Không thể tìm thấy một tập lệnh hoặc một đối tượng mở rộng được liên kết với không gian tên 'xalan: // java.lang.String'.' –

+0

Động cơ XSLT của bạn là gì? –

+0

Microsoft.NET mà tôi sợ ... –

5

Bạn có thể sử dụng đoạn mã sau khi bộ vi xử lý của bạn chạy trên .NET hoặc sử dụng MSXML (trái ngược với bộ vi xử lý gốc Java hoặc các bộ xử lý gốc khác). Nó sử dụng msxsl:script.

Đảm bảo thêm không gian tên xmlns:msxsl="urn:schemas-microsoft-com:xslt" vào phần tử gốc xsl:stylesheet hoặc xsl:transform của bạn.

Ngoài ra, hãy liên kết outlet với bất kỳ không gian tên nào bạn muốn, ví dụ: 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

Xin lỗi nếu tôi bị câm, nhưng tôi nhận được 'tiền tố outlet không được định nghĩa' hoặc' 'xsl: script' không thể là con của phần tử 'xsl: stylesheet'' nếu tôi thay đổi msxsl cho tiền tố của mình. Tôi đoán đây là một số phép thuật XSLT dành riêng cho Microsoft? –

+1

@IanGrainger, nó không phải là 'xsl: script', nhưng' msxsl: script' và nó có một không gian tên khác (tôi đã cập nhật câu trả lời của John). – Abel

0

Các rouine là khá tốt, tuy nhiên nó gây ra ứng dụng của tôi để treo, vì vậy tôi cần phải thêm các trường hợp:

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

trước khi chức năng được gọi là đệ quy.

tôi có câu trả lời từ đây: When test hanging in an infinite loop

Cảm ơn bạn!