Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xslt Umbraco-创建节点变量-如何检查缺少的值_Xslt_Xslt 1.0_Umbraco_Xslt 2.0 - Fatal编程技术网

Xslt Umbraco-创建节点变量-如何检查缺少的值

Xslt Umbraco-创建节点变量-如何检查缺少的值,xslt,xslt-1.0,umbraco,xslt-2.0,Xslt,Xslt 1.0,Umbraco,Xslt 2.0,我正在使用Umbraco 4.5(是的,我知道我现在应该升级到7!) 我有一个XSLT转换,它建立了一个与用户过滤器匹配的产品列表 我正在制作一个XSL:variable,它是CMS数据库中产品的集合 每个产品都有几个是/否属性(单选按钮)。然而,其中一些还没有被填充 因此,如果数据集包含的产品没有使用答案填充选项之一,则以下代码偶尔会中断 我在转换XSLT时遇到的错误是“值对于Int32来说太大或太小”。我假设这是传递到GetPreValueAsString方法中的值 如何检查./option

我正在使用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 2.0,但Umbraco不使用XSLT 2.0,它(目前)仍然使用XSLT 1.0

您的错误可能有多种原因。处理器不需要从左到右或从右到左处理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.
3.
4.
注意(1):我手工编写了上面的代码,只测试了语法错误,我无法测试它,因为您没有提供输入文档来测试它。如果您发现错误,请务必编辑我的回复,使其正确无误

注(2):上述代码概括了使用编号参数的工作。通过对其进行泛化,代码变得更加复杂,但更易于维护和扩展,并且不容易出现复制/粘贴错误

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