xsl:value-of xsl:variable的子代的后果

时间:2011-04-26 16:37:52

标签: xslt

$world是元素列表时,这三个块在副作用方面有何不同?我看到第一个和第三个之间有不同的行为,无法理解它。

<xsl:variable name="hello" select="$world" />

<xsl:variable name="hello">
    <xsl:value-of select="$world" />
</xsl:variable>

<xsl:variable name="hello">
    <xsl:choose>
        <xsl:when test="$something=true()">
            <xsl:value-of select="$world" />
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$world" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

编辑1:我想在$hello中处理<xsl:for-each select="$hello">。使用上面的第三个块<xsl:for-each>只有一个要处理的项目,其中包含$world的连接内容。那是为什么?

3 个答案:

答案 0 :(得分:2)

第一个xsl:variable的值和类型与$world相同。第二个是结果树片段,其中单个文本节点的字符串值为$world。第三个也是一个带有单个文本节点的结果树片段。

我想你想要

  <xsl:variable name="hello" select="if (condition) then $world else $foo"/>

在XSLT 2.0中,然后你的for-each select="$hello"可以按你的需要工作,或者在你想要的XSLT 1.0和EXSLT中使用

<xsl:variable name="hello">
  <xsl:choose>
    <xsl:when test="condition">
      <xsl:copy-of select="$world"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy-of select="$foo"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:for-each select="exsl:node-set($hello)/*">...</xsl:for-each>

答案 1 :(得分:1)

虽然所有三个示例在XSLT 1.0和XSLT 2.0中都有效,但描述语义的方式在两个规范中是非常不同的。当$ value包含多个节点时,<xsl:value-of select="$value"/>的效果取决于样式表是指定version =“1.0”还是version =“2.0”。

要记住的主要事项,适用于两个版本,是(a)xsl:value-of通过将其选择的任何内容转换为字符串来创建文本节点,以及(b)xsl:包含指令的变量(并且不“as”属性创建一个以文档节点为根的新树。

答案 2 :(得分:0)

  <xsl:variable name="hello">
      <xsl:choose>
          <xsl:when test="$something=true()">
              <xsl:value-of select="$world" />
          </xsl:when>
          <xsl:otherwise>
              <xsl:value-of select="$world" />
          </xsl:otherwise>            
         </xsl:choose>        
    </xsl:variable>
     

我想在a中处理$hello   <xsl:for-each select="$hello">。同   <xsl:for-each>上方的块有   只包含一个要处理的项目   $world的联合内容。为什么是   是什么?

名为$hello的变量包含字符串值$world。根据定义,这是<xsl:value-of>在XSLT 1.0中的行为。

您没有向我们展示如何定义$world,但如果它包含单个元素或整个文档树,那么(再次)按照定义,其字符串值是连接(按文档顺序)它的所有后代 - 文本节点。

这正是你所看到的。

如果是

,则情况会有所不同
<xsl:value-of select="$world" />

您使用

<xsl:copy-of select="$world" />

这将复制整个子树,其根是/中包含的$world包含完整文档的情况下的元素(或根节点$world)。

但是,在XSLT 1.0中,这会创建所谓的RTF(结果树片段),根据定义,不能将RTF用作XPath(1.0)表达式中的位置步骤。

首先必须使用供应商提供的扩展函数将其转换为常规树(文档节点),该扩展函数通常具有本地名称node-set,但在特定于供应商的命名空间中。

典型的例子是

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vWorld" select="/*"/>

 <xsl:template match="/">
  <xsl:variable name="vrtfHello">
    <xsl:copy-of select="$vWorld"/>
  </xsl:variable>

  <xsl:variable name="vHello" select=
   "ext:node-set($vrtfHello)/*"/>

  <xsl:copy-of select="$vHello/*[3]"/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档时:

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

结果(正如预期的那样):

<num>03</num>

这里我们在名称空间“http://exslt.org/common”中使用ext:node-set()扩展函数,该函数由EXSLT独立于供应商的库指定。大多数XSLT 1.0处理器都支持EXSLT,并且使用其node-set()扩展功能并不会降低所有此类XSLT处理器上XSLT应用程序的可移植性。