选择的惯用替代方案 -> 测试 -> 值 (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, '|')"/>