سؤال

أنا رمز سلسلة مع 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 ؛

(ال £ و $ المؤشرات موجودة فقط حتى أتمكن من رؤية أي سلاسل فارغة يتم إخراجها. هذا داخل 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> حظر عندما لا ينبغي.


شرح أكثر تفصيلا لما يحدث ولماذا يحلق:

هناك ثلاثة فروع في <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 عندما تكون المعلمة الثانية فارغة أو لا شيء. أظهرت الاختبارات أن محرك XSLT من Microsoft Visual Studio true عندما تكون المعلمة الثانية إما فارغة أو لا شيء. لست متأكدًا مما إذا كان هذا هو السلوك المحدد أو إذا كان الأمر متروكًا للمنفذ لتقريره. هل لدى أي شخص إجابة قاطعة على هذا؟ تومالاك ، أنا أنظر إليك.

نصائح أخرى

ليس string كلمة محجوزة؟ هل يمكنك محاولة استبدال هذا الاسم لأي شيء آخر؟

تعديل: تم تشغيل الرمز الموفر بدون مشكلة هنا: XSLT Tryit Editor 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