Umbraco -创建节点变量-如何检查缺失值



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

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

我正在制作一个XSL:变量,它是来自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 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):以上代码泛化了带编号参数的工作。通过泛化它,代码变得有点复杂,但它变得更容易维护和扩展,并且更不容易出现复制/粘贴错误。

相关内容

  • 没有找到相关文章

最新更新