XSLT 문자열 교체


85

XSL을 잘 모르지만이 코드를 수정해야합니다. 더 간단하게 만들기 위해 줄였습니다.
이 오류가 발생합니다.

잘못된 XSLT / XPath 함수

이 줄에

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

누구에게 무엇이 문제인지 말해 줄 수 있습니까?


replace()함수는 XPath 2.0 (따라서 XSLT 2.0)부터 사용할 수 있으며 정규식 대체를 지원합니다.
Abel

답변:


147

replace XSLT 1.0에서는 사용할 수 없습니다.

Codesling에는 함수 대신 사용할 수있는 문자열 교체 템플릿 이 있습니다.

<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원래 코드에서와 동일한 작업을 수행 할 수 없습니다 .


감사합니다 Mark,하지만 이제이 오류가 발생합니다. 알 수없는 XPath 확장 기능이 호출되었습니다
Aximili

@aximili, 죄송합니다. XSLT 1.0과 2.0이 혼란스럽고 편집되었습니다 ... 지금 가면 좋을 것입니다.
Mark Elliot

19
이 대답은 틀 렸습니다! XSLT의 바꾸기 기능은 전체 문자열이 아닌 해당 단일 문자를 대체합니다! 여기 예를 들어, 참조 : w3schools.com/xpath/xpath_functions.asp
야쿱

12
@Jakub 당신은 생각하고 translate있지 않습니다 replace. replaceXPath 2.0 의 함수는 두 번째 인수를 정규식 으로 취급하고 해당 식의 모든 일치 항목을 지정된 대체 문자열 ( $n정규식에서 그룹 캡처에 대한 참조를 포함 할 수 있음)으로 바꿉니다 . translate(1.0 및 2.0) 기능은 단일 문자를 위해 단일 문자 교체를 수행 한 것이다.
Ian Roberts

6
예제 사용법의 네 번째 줄 <xsl:with-param name="replace" select="'a'" />은 a를 따옴표로 묶어야하지 않습니까?
DJL

37

다음은 C #의 String.Replace () 함수와 유사하게 작동하는 XSLT 함수입니다.

이 템플릿에는 아래와 같이 3 개의 매개 변수가 있습니다.

텍스트 :-기본 문자열

교체 :- 교체 하려는 문자열

by :-새 문자열로 응답 할 문자열

아래는 템플릿입니다

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

자세한 내용은 아래 URL 을 참조 하십시오.


1
xslt 1.0 사용이 게시물 / 템플릿은 Mark Elliot가 그렇지 않은 동안 저에게 효과적이었습니다.
HostMyBus

12

참고 : 소스 문자열에서 많은 수의 인스턴스를 교체해야하는 경우 (예 : 긴 텍스트의 새 줄) 이미 언급 한 알고리즘을 사용하려는 경우 재귀 로 인해 끝날 가능성 이 높습니다.StackOverflowException 요구.

Xalan ( Saxon 에서 수행하는 방법을 보지 않음 ) 내장 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>

죄송합니다 내가 바보 인거야하지만 난 얻을 경우 :Cannot find a script or an extension object associated with namespace 'xalan://java.lang.String'.
이안 그레인저

XSLT 엔진은 무엇입니까?
Milan Aleksić 2014 년

3
내 의견은 사용 가능한 Java 클래스 경로 내에서 사용 가능한 유형에 대한 직접 매핑을 지원하는 가장 인기있는 Java XSLT 1.0 엔진 Xalan ( xml.apache.org/xalan-j )에 대한 것입니다. 당신은 닷넷 스택에 대한 내 솔루션을 적용 할 수 없습니다
밀란 알렉 식

@IanGrainger, <msxsl:script>모든 .NET 메소드, 라이브러리 등을 호출 할 수 있는 블록 을 추가하여 .NET과 함께 사용할 수 있습니다 . .NET도 EXSLT 확장 기능을 지원하기 때문에 필요하지 않습니다.
Abel

EXSLT는 도에서 지원됩니다 libxslt를 따라서 모든 후손에 xsltproc 등 ...
알랭 Pannetier

7

프로세서가 .NET에서 실행되거나 MSXML (Java 기반 또는 기타 기본 프로세서와 반대)을 사용하는 경우 다음 코드를 사용할 수 있습니다. 그것은 msxsl:script.

xmlns:msxsl="urn:schemas-microsoft-com:xslt"루트 xsl:stylesheet또는 xsl: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')" />

내가 바보 같으면 미안하지만 내 접두사에 대해 msxsl을 얻 prefix outlet is not defined거나 'xsl:script' cannot be a child of the 'xsl:stylesheet' element.변경하면. 이것이 Microsoft 고유의 XSLT 마법이라고 생각합니까?
Ian Grainger

1
@IanGrainger, 그것은 xsl:script아니지만 msxsl:script, 다른 네임 스페이스를 가지고 있습니다 (John의 답변을 업데이트했습니다).
Abel

1

나는이 대답을 계속칩니다. 그러나 그들 중 어느 것도 xsltproc (그리고 아마도 대부분의 XSLT 1.0 프로세서)에 대한 가장 쉬운 솔루션을 나열하지 않습니다.

  1. exslt 문자열 이름을 스타일 시트에 추가합니다.
<xsl:stylesheet
  version="1.0"
  xmlns:str="http://exslt.org/strings"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  1. 그런 다음 다음과 같이 사용하십시오.
<xsl:value-of select="str:replace(., ' ', '')"/>

1
내 컴퓨터 (macOS 10.13)의 xsltproc이이 str:replace()기능을 지원하지 않습니다 . Xalan, Saxon 6.5 및 Microsoft와 같은 다른 주요 XSLT 1.0 프로세서도 마찬가지입니다.
michael.hor257k

0

루틴은 꽤 좋지만 앱이 중단되므로 케이스를 추가해야합니다.

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

함수가 재귀 적으로 호출되기 전에.

나는 여기에서 답을 얻었습니다 : 무한 루프에서 테스트가 걸려있을 때

감사합니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.