Frage

Ich token mag eine Saite mit XSLT 1.0 und versuche zu verhindern, dass leere Saiten als Token erkannt werden. Hier ist die gesamte Funktion basierend auf XSLT -Kochbuch:

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

Wert für string dass ich vorbeikomme::

Europa;#6; #global;#3; #middle Ost, Afrika und Kaukasus; 2; #europa;#6; #global;#3; #middle Ost, Afrika und Kaukasus

(Das £ und $ Indikatoren sind nur da, sodass ich keine leeren Saiten ausgeben kann. Dies ist innerhalb von SharePoint, daher ist es schwer zu debuggen.)

Dieser Code hängt die Verarbeitung des XSLT auf. Die Linie, die das Problem verursacht, ist <xsl:when test="not($delimiter) and $string != ''">. Sobald ich die zweite entferte and Testen Sie es funktioniert wieder. Ich habe es auch versucht and string($string) ohne Erfolg.

Weiß jemand, warum das passiert und wie man es behebt?

War es hilfreich?

Lösung

Ich glaube, mein Verdacht war richtig: Sie fallen zu Ihrem durch <xsl:otherwise> Klausel wann $string hat einen Wert, aber $delimiter verursacht nicht, wie Sie sagen.

Fügen Sie das folgende neue hinzu <xsl:when> Klausel nach dem ersten:

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

Dies verhindert, dass die Ausführung in das Eintritt in die <xsl:otherwise> Blockieren Sie, wenn es nicht sollte.


Eine ausführlichere Erklärung für das, was los ist und warum es Schleifen ist:

Es gibt drei Zweige in der <xsl:choose> Block.

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

Also, wenn weder $string Noch $delimiter Werte enthalten, die erste Bedingung schlägt fehl (weil $string != '' ist falsch). Der zweite Zustand geht (weil contains(nil,nil) Gibt immer True zurück (in Visual Studio bestätigt), was die Vorlage erneut mit denselben Parametern aufruft (weil die substring-before Gibt die leere Zeichenfolge zurück, da er den leeren Trennzeichen nicht enthält). Ergo, eine unendliche Schleife.

Die Lösung besteht darin, einen neuen, leeren Zustand hinzuzufügen:

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

Bearbeiten: Ich habe herumgestoßen und kann keinen Bezug auf das definierte Verhalten von finden contains Wenn der zweite Parameter leer oder nil ist. Tests haben gezeigt, dass die XSLT -Engine von Microsoft Visual Studio zurückkehrt true Wenn der zweite Parameter entweder leer oder nil ist. Ich bin mir nicht sicher, ob dies das definierte Verhalten ist oder ob es am Implementierer liegt, zu entscheiden. Hat jemand eine schlüssige Antwort darauf? Tomalak, ich schaue dich an.

Andere Tipps

Nicht string Ein reserviertes Wort? Können Sie versuchen, diesen Namen für etwas anderes zu ersetzen?

BEARBEITEN: Der gelieferte Code lief hier ohne Probleme: XSLT Tryit Editor v1.0 Verwenden:

<xsl:call-template name="tokenize">
   <xsl:with-param name="string">Europe;#6;#Global...</xsl:with-param>
</xsl:call-template>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top