选择的惯用替代方案 -> 测试 -> 值 (XSLT 1.0)
idiomatic alternative to choose -> test -> value-of (XSLT 1.0)
在我的工作中,我似乎看到很多代码都是这样的..
<xsl:choose>
<xsl:when test="long_xpath_to_optional/@value1">
<xsl:value-of select="long_xpath_to_optional/@value"/>
</xsl:when>
<xsl:when test="another_long_xpath_to_optional/@value">
<xsl:value-of select="another_long_xpath_to_optional/@value"/>
</xsl:when>
<etc>
</etc>
<otherwise>
<xsl:value-of select="default_long_xpath_to_value"/>
</otherwise>
</xsl:choose>
它很长而且很重复。
当我使用其他(伪)语言工作时,我会去
let values = concat(list(long_xpath_to_optional_value),list(another_long_xpath_to_optional_value))
let answer = tryhead(values,default_long_xpath_to_value)
即按优先顺序创建一个值列表,然后取头。
我只评估每条路径一次
您将如何在 XSLT 1.0 中做类似的事情(我们可以使用节点集)。
使用你写的变量
<xsl:variable name="value1" select="long_xpath_to_optional/@value1"/>
<xsl:variable name="value2" select="another_long_xpath_to_optional/@value"/>
<xsl:variable name="value3" select="default_long_xpath_to_value"/>
然后在 XPath 2 或 3 中,您只需要 ($value1, $value2, $value3)[1]
或 head(($value1, $value2, $value3))
但在带有 XPath 1 的 XSLT 1 中,您可以作为单个表达式编写的是 ($value1 | $value2 | $value3)[1]
按文档顺序排序,因此除非文档顺序与您的测试顺序相同,否则无法检查值;相反,您需要维护
<xsl:choose>
<xsl:when test="$value1">
<xsl:value-of select="$value1"/>
</xsl:when>
<xsl:when test="$value2">
<xsl:value-of select="$value2"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value3"/>
</xsl:otherwise>
</xsl:choose>
当然,在 XPath 2 中,您实际上并不需要变量,也可以直接使用 (long_xpath_to_optional/@value1, another_long_xpath_to_optional/@value, default_long_xpath_to_value)[1]
。
I was wondering if you can create a node-set somehow
你可以 - 但它不会更短:
<xsl:variable name="values">
<xsl:apply-templates select="long_xpath_to_optional/@value" mode="values"/>
<xsl:apply-templates select="another_long_xpath_to_optional/@value" mode="values"/>
<xsl:apply-templates select="default_long_xpath_to_value/@value" mode="values"/>
</xsl:variable>
<xsl:value-of select="exsl:node-set($values)/value[1]" xmlns:exsl="http://exslt.org/common"/>
然后:
<xsl:template match="@value" mode="values">
<value>
<xsl:value-of select="."/>
</value>
</xsl:template>
但至少消除了重复
或者,您可以这样做:
<xsl:template match="@value" mode="values">
<xsl:value-of select="."/>
<xsl:text>|</xsl:text>
</xsl:template>
然后:
<xsl:value-of select="substring-before($values, '|')"/>
在我的工作中,我似乎看到很多代码都是这样的..
<xsl:choose>
<xsl:when test="long_xpath_to_optional/@value1">
<xsl:value-of select="long_xpath_to_optional/@value"/>
</xsl:when>
<xsl:when test="another_long_xpath_to_optional/@value">
<xsl:value-of select="another_long_xpath_to_optional/@value"/>
</xsl:when>
<etc>
</etc>
<otherwise>
<xsl:value-of select="default_long_xpath_to_value"/>
</otherwise>
</xsl:choose>
它很长而且很重复。
当我使用其他(伪)语言工作时,我会去
let values = concat(list(long_xpath_to_optional_value),list(another_long_xpath_to_optional_value))
let answer = tryhead(values,default_long_xpath_to_value)
即按优先顺序创建一个值列表,然后取头。 我只评估每条路径一次
您将如何在 XSLT 1.0 中做类似的事情(我们可以使用节点集)。
使用你写的变量
<xsl:variable name="value1" select="long_xpath_to_optional/@value1"/>
<xsl:variable name="value2" select="another_long_xpath_to_optional/@value"/>
<xsl:variable name="value3" select="default_long_xpath_to_value"/>
然后在 XPath 2 或 3 中,您只需要 ($value1, $value2, $value3)[1]
或 head(($value1, $value2, $value3))
但在带有 XPath 1 的 XSLT 1 中,您可以作为单个表达式编写的是 ($value1 | $value2 | $value3)[1]
按文档顺序排序,因此除非文档顺序与您的测试顺序相同,否则无法检查值;相反,您需要维护
<xsl:choose>
<xsl:when test="$value1">
<xsl:value-of select="$value1"/>
</xsl:when>
<xsl:when test="$value2">
<xsl:value-of select="$value2"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value3"/>
</xsl:otherwise>
</xsl:choose>
当然,在 XPath 2 中,您实际上并不需要变量,也可以直接使用 (long_xpath_to_optional/@value1, another_long_xpath_to_optional/@value, default_long_xpath_to_value)[1]
。
I was wondering if you can create a node-set somehow
你可以 - 但它不会更短:
<xsl:variable name="values">
<xsl:apply-templates select="long_xpath_to_optional/@value" mode="values"/>
<xsl:apply-templates select="another_long_xpath_to_optional/@value" mode="values"/>
<xsl:apply-templates select="default_long_xpath_to_value/@value" mode="values"/>
</xsl:variable>
<xsl:value-of select="exsl:node-set($values)/value[1]" xmlns:exsl="http://exslt.org/common"/>
然后:
<xsl:template match="@value" mode="values">
<value>
<xsl:value-of select="."/>
</value>
</xsl:template>
但至少消除了重复
或者,您可以这样做:
<xsl:template match="@value" mode="values">
<xsl:value-of select="."/>
<xsl:text>|</xsl:text>
</xsl:template>
然后:
<xsl:value-of select="substring-before($values, '|')"/>