【问题标题】:Umbraco - Creating variable of nodes - how to check for missing valueUmbraco - 创建节点变量 - 如何检查缺失值
【发布时间】:2015-08-26 08:25:29
【问题描述】:

我正在使用 Umbraco 4.5(是的,我知道我现在应该升级到 7!)

我有一个 XSLT 转换,它建立了一个与用户过滤器匹配的产品列表。

我正在制作一个 XSL:variable,它是 CMS 数据库中的产品集合。

每个产品都有几个是/否属性(单选按钮)。然而,其中一些还没有被填充。

因此,如果数据集包含的产品没有填充有答案的选项之一,则以下代码偶尔会中断。

我在转换 XSLT 时遇到的错误是“对于 Int32,值太大或太小”。我假设这是传递给 GetPreValueAsString 方法的值。

如何检查 ./option1 是否为空,如果是,则使用特定整数,否则使用 ./option1

<xsl:variable name="nodes" 
    select="umbraco.library:GetXmlNodeById(1098)/* 
    [@isDoc and string(umbracoNaviHide) != '1' and 
    ($option1= '' or $option1=umbraco.library:GetPreValueAsString(./option1)) and
    ($option2= '' or $option2=umbraco.library:GetPreValueAsString(./option2)) and
    ($option3= '' or $option3=umbraco.library:GetPreValueAsString(./option3)) and
    ($option4= '' or $option4=umbraco.library:GetPreValueAsString(./option4)) 
    ]" />

【问题讨论】:

    标签: xslt xslt-1.0 umbraco xslt-2.0


    【解决方案1】:

    注意:您将问题标记为 XSLT 2.0,但 Umbraco 不使用 XSLT 2.0,它(目前)卡在 XSLT 1.0 上。

    $option1= '' or $option1=umbraco.library:GetPreValueAsString(./option1)
    

    您的错误可能有多种原因。处理器不需要从左到右或从右到左处理 or 表达式,甚至允许始终计算两个表达式,即使第一个表达式为真(这与按位运算符 (无序)在其他语言中,而这些语言中的布尔运算符(有序)通常使用早期突破)。

    另一个错误可能是上下文节点中的选项值不为空,也不是整数或空,在这种情况下,您的代码将始终返回错误。

    你可以通过测试./optionX来扩展你的表达式,但是你仍然有评估顺序的问题。

    也就是说,您如何解决它并防止出现错误?在 XSLT 1.0 中,这有点笨拙(即,您不能定义函数,也不能使用序列),但这里有一种方法:

    <xsl:variable name="pre-default-option">
        <default>1</default>
        <default>2</default>
        <default>3</default>
        <default>4</default>
    </xsl:variable>
    
    <xsl:variable name="default-option"
        select="exslt:node-set($pre-default-option)" />
    
    <xsl:variable name="pre-selected-option">
        <option><xsl:value-of select="$option1" /></option>
        <option><xsl:value-of select="$option2" /></option>
        <option><xsl:value-of select="$option3" /></option>
        <option><xsl:value-of select="$option4" /></option>
    </xsl:variable>
    
    <xsl:variable name="selected-option" select="exslt:node-set($pre-selected-option)" />
    
    <xsl:variable name="pre-process-nodes">
        <xsl:variable name="selection">
            <xsl:apply-templates 
                select="umbraco.library:GetXmlNodeById(1098)/*"
                mode="pre">
                <xsl:with-param name="opt-no" select="1" />
            </xsl:apply-templates>
        </xsl:variable>
    
        <!-- your original code uses 'and', so is only true if all 
             conditions are met, hence there must be four found nodes, 
             otherwise it is false (i.e., this node set will be empty) -->
        <xsl:if test="count($selection) = 4">
             <xsl:copy-of select="$selection" />
        </xsl:if>
    </xsl:variable>
    
    <!-- your original variable, should now contain correct set, no errors -->
    <xsl:variable name="nodes" select="exslt:node-set($pre-process-nodes)"/>
    
    <xsl:template match="*[@isDoc and string(umbracoNaviHide) != '1']" mode="pre">
        <xsl:param name="opt-no" />
    
        <xsl:variable name="option"
            select="$selected-option[. = string($opt-no)]" />
    
        <!-- gets the child node 'option1', 'option2' etc -->
        <xsl:variable 
            name="pre-ctx-option" 
            select="*[local-name() = concat('option', $opt-no)]" />
    
        <xsl:variable name="ctx-option">
            <xsl:choose>
    
                <!-- empty option param always allowed -->
                <xsl:when test="$option = ''">
                    <xsl:value-of select="$option"/>
                </xsl:when>
    
                <!-- if NaN or 0, this will return false -->
                <xsl:when test="number($pre-ctx-option)">
                    <xsl:value-of select="$default-option[$opt-no]"/>
                </xsl:when>
    
                <!-- valid number (though you could add a range check as well) -->
                <xsl:otherwise>
                    <xsl:value-of select="umbraco.library:GetPreValueAsString($pre-ctx-option)"/>
                </xsl:otherwise>
             </xsl:choose>
        </xsl:variable>
    
        <!-- prevent eternal recursion -->
        <xsl:if test="4 >= $opt-no">
            <xsl:apply-templates select="self::*" mode="pre">
                <xsl:with-param name="opt-no" select="$opt-no + 1" />
            </xsl:apply-templates>
            <!-- the predicate is now ctx-independent and just true/false
                 this copies nothing if the conditions are not met -->
            <xsl:copy-of select="self::*[$option = $ctx-option]" />
        </xsl:if>
    </xsl:template>
    
    <xsl:template match="*" mode="pre" />
    

    注(1):上面的代码是我手写的,只测试了语法错误,我无法测试它,因为你没有提供一个输入文档来测试它。如果您发现错误,请务必编辑我的回复以使其正确。

    注(2):上面的代码概括了使用编号参数的工作。通过概括它,代码变得有点复杂,但它变得更容易维护和扩展,并且更不容易出现复制/粘贴错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 2011-08-16
      相关资源
      最近更新 更多