문제

나는 XSLT 1.0으로 문자열을 토큰 화하고 빈 줄이 토큰으로 인식되는 것을 방지하려고 노력하고 있습니다. 다음은 전체 기능을 기반으로합니다 XSLT 요리 책:

<xsl:template name="tokenize">
    <xsl:param name="string" select="''" />
    <xsl:param name="delimiters" select="';#'" />
    <xsl:param name="tokensplitter" select="','" />
    <xsl:choose>
        <!-- Nothing to do if empty string -->
        <xsl:when test="not($string)" />

        <!-- No delimiters signals character level tokenization -->
        <xsl:when test="not($delimiters)">
            <xsl:call-template name="_tokenize-characters">
                <xsl:with-param name="string" select="$string" />
                <xsl:with-param name="tokensplitter" select="$tokensplitter" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:call-template name="_tokenize-delimiters">
                <xsl:with-param name="string" select="$string" />
                <xsl:with-param name="delimiters" select="$delimiters" />
                <xsl:with-param name="tokensplitter" select="$tokensplitter" />
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="_tokenize-characters">
    <xsl:param name="string" />
    <xsl:param name="tokensplitter" />
    <xsl:if test="$string">
        <token><xsl:value-of select="substring($string, 1, 1)"/></token>
        <xsl:call-template name="_tokenize-characters">
            <xsl:with-param name="string" select="substring($string, 2)" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template name="_tokenize-delimiters">
    <xsl:param name="string" />
    <xsl:param name="delimiters" />
    <xsl:param name="tokensplitter" />

    <!-- Extract a delimiter -->
    <xsl:variable name="delimiter" select="substring($delimiters, 1, 1)"/>
    <xsl:choose>
        <!-- If the delimiter is empty we have a token -->
        <xsl:when test="not($delimiter) and $string != ''">
            <xsl:text>£</xsl:text>
            <token><xsl:value-of select="$string"/></token>
            <xsl:text>$</xsl:text>
            <xsl:value-of select="$tokensplitter"/>
        </xsl:when>
        <!-- If the string contains at least one delimiter we must split it -->
        <xsl:when test="contains($string, $delimiter)">
            <!-- If it starts with the delimiter we don't need to handle the before part -->
            <xsl:if test="not(starts-with($string, $delimiter))">
                <!-- Handle the part that comes before the current delimiter with the next delimiter. -->
                <!-- If there is no next the first test in this template will detect the token. -->
                <xsl:call-template name="_tokenize-delimiters">
                    <xsl:with-param name="string" select="substring-before($string, $delimiter)" />
                    <xsl:with-param name="delimiters" select="substring($delimiters, 2)" />
                    <xsl:with-param name="tokensplitter" select="$tokensplitter" />
                </xsl:call-template>
            </xsl:if>
            <!-- Handle the part that comes after the delimiter using the current delimiter -->
            <xsl:call-template name="_tokenize-delimiters">
                <xsl:with-param name="string" select="substring-after($string, $delimiter)" />
                <xsl:with-param name="delimiters" select="$delimiters" />
                <xsl:with-param name="tokensplitter" select="$tokensplitter" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <!-- No occurrences of current delimiter so move on to next -->
            <xsl:call-template name="_tokenize-delimiters">
                <xsl:with-param name="string" select="$string" />
                <xsl:with-param name="delimiters" select="substring($delimiters, 2)" />
                <xsl:with-param name="tokensplitter" select="$tokensplitter" />
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

가치 string 내가 지나가는 것은 다음과 같습니다.

유럽;#6;#Global;#3; #Middle East, Africa and Caucasus; 2; #Europe;#6;#3; #Middle East, Africa 및 Caucasus

(그만큼 £ 그리고 $ 표시기가 바로 거기에 있으므로 빈 문자열이 출력되지 않는 것을 볼 수 있습니다. 이것은 SharePoint 내에 있으므로 디버그하기가 어렵습니다.)

이 코드는 XSLT의 처리를 중단합니다. 문제를 일으키는 라인은입니다 <xsl:when test="not($delimiter) and $string != ''">. 두 번째를 제거하자마자 and 다시 작동합니다. 나는 또한 시도했다 and string($string) 성공없이.

왜 이런 일이 일어나고 있는지, 어떻게 해결하는지 아는 사람이 있습니까?

도움이 되었습니까?

해결책

나는 내 의심이 옳았다 고 생각한다 : 당신은 당신에게 <xsl:otherwise> 조항시기 $string 가치는 있지만 $delimiter 당신이 말하는 것처럼 무한 루프를 유발하지 않습니다.

다음 새를 추가하십시오 <xsl:when> 첫 번째 조항 : 첫 번째 조항 :

    <xsl:when test="not($delimiter) and $string = ''" />

이는 실행이 입력되는 것을 막을 것입니다 <xsl:otherwise> 그렇지 않으면 차단하십시오.


무슨 일이 일어나고 있는지, 왜 반복되는지에 대한보다 정교한 설명 :

3 개의 가지가 있습니다 <xsl:choose> 차단하다.

    <xsl:when test="not($delimiter) and $string != ''">
    <xsl:when test="contains($string, $delimiter)">
    <xsl:otherwise>

그래서, 둘 다 $string ...도 아니다 $delimiter 값이 포함되어 있으면 첫 번째 조건이 실패합니다 $string != '' 거짓). 두 번째 조건은 통과합니다 (때문에 contains(nil,nil) 항상 true (Visual Studio에서 확인)를 반환합니다.이 템플릿은 동일한 매개 변수로 다시 호출 substring-before 빈 구분기가 포함되어 있지 않으므로 빈 문자열을 반환합니다). 무한 루프 인 Ergo.

수정 사항은 새롭고 빈 상태를 추가하는 것입니다.

    <xsl:when test="not($delimiter) and $string != ''">
    <xsl:when test="not($delimiter) and $string = ''" />
    <xsl:when test="contains($string, $delimiter)">
    <xsl:otherwise>

편집 : 나는 주위를 찌르고 정의 된 행동에 대한 언급을 찾을 수 없습니다. contains 두 번째 매개 변수가 비어 있거나 nil 일 때. 테스트 결과 Microsoft Visual Studio의 XSLT 엔진이 반환됩니다. true 두 번째 매개 변수가 비어 있거나 nil 일 때. 그것이 정의 된 동작인지 또는 결정을 내릴 수있는 구현 자에게 달려 있는지 확실하지 않습니다. 누구든지 이것에 대한 결정적인 대답이 있습니까? Tomalak, 나는 당신을보고 있습니다.

다른 팁

그렇지 않습니다 string 예약 된 단어? 다른 이름으로 그 이름을 바꿀 수 있습니까?

편집하다: 제공된 코드는 여기에서 문제없이 실행되었습니다. XSLT Tryit 편집기 v1.0 사용 :

<xsl:call-template name="tokenize">
   <xsl:with-param name="string">Europe;#6;#Global...</xsl:with-param>
</xsl:call-template>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top