xsl:value-of 作为 xsl:variable 子级的后果

发布于 2024-11-03 17:54:04 字数 799 浏览 1 评论 0 原文

$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 。对于上面的第三个块, 只有一项要处理,其中包含 $world 的连接内容。这是为什么?

What is the differences between these three blocks in terms of side-effects when $world is a list of elements? I am seeing a different behaviour between the first and the third and cannot get my head around it.

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

Edit 1: I want to process $hello in a <xsl:for-each select="$hello">. With the third block above the <xsl:for-each> has only one item to process that contains the joined contents of $world. Why is that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

诠释孤独 2024-11-10 17:54:04

第一个 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 common 中工作

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

The first xsl:variable will have the same value and type as $world. The second is a result tree fragment with a single text node of the string value of $world. The third is also a result tree fragment with a single text node.

I guess you want either

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

in XSLT 2.0 and then your for-each select="$hello" would work as you want or in XSLT 1.0 plus EXSLT common you want

<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>
╰ゝ天使的微笑 2024-11-10 17:54:04

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

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

While all three examples are valid in both XSLT 1.0 and XSLT 2.0, the way the semantics are described is very different in the two specs; also when $value contains multiple nodes, the effect of <xsl:value-of select="$value"/> depends on whether the stylesheet specifies version="1.0" or version="2.0".

The main things to remember, that apply to both versions, are (a) xsl:value-of creates a text node by converting whatever it selects into a string, and (b) xsl:variable with contained instructions (and no "as" attribute) creates a new tree rooted at a document node.

时光礼记 2024-11-10 17:54:04
 
      
          
              
          
          
              
                      
                 
    

我想在 a 中处理 $hello
。和
上方的块有
只有一项要处理的项目包含
$world 的连接内容。为什么是
那?

名为 $hello 的变量包含 $world 的字符串值。根据定义,这就是 在 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>

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

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

I want to process $hello in a
<xsl:for-each select="$hello">. With
the block above the <xsl:for-each> has
only one item to process that contains
the joined contents of $world. Why is
that?

The variable named $hello contains the string value of $world. This is by definition how <xsl:value-of> behaves in XSLT 1.0.

You haven't shown us how $world is defined, but if it contains a single element or a whole document tree, then (again) by definition, its string value is the concatenation (in document order) of all of its descendents - text nodes.

This is exactly what you are seeing.

The situation will be different if insead of:

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

you use:

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

This copies the whole subtree whose root is the element (or root node / in the case when $world contains a complete document) contained in $world.

However, in XSLT 1.0 this creates the so called RTF (Result Tree Fragment) and by definition one cannot use an RTF as a location step in XPath (1.0) expression.

One must first convert this to a regular tree (document node) using a vendor-supplied extension function that most often has the local-name node-set but is in a vendor-specific namespace.

A typical example is:

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

when this transformation is applied on the following XML document:

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

the result is (as expected):

<num>03</num>

Here we use the ext:node-set() extension function in the namespace "http://exslt.org/common" as specified by the EXSLT vendor-independent library. Most XSLT 1.0 processors support EXSLT and using its node-set() extension function doesn't decrease the degree of portability of an XSLT application accross all such XSLT processors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文