构造而不是选择XSL节点集变量

时间:2015-02-20 14:54:16

标签: xslt xslt-1.0 msxsl

我希望使用包含的for-each循环构造一个XSL节点集变量。重要的是构造的节点集是原始(选定的)节点集,而不是副本。

这是我的问题的一个简化版本(当然可以通过选择解决,但这不是问题的重点)。我使用了< name>用于测试构造的节点集变量实际上是在原始树中而不是副本的节点。

XSL 1.0版,处理器是msxsl。

非工作XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="iso-8859-1" omit-xml-declaration="yes" />

<xsl:template match="/">

    <xsl:variable name="entries">
        <xsl:for-each select="//entry">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="entryNodes" select="msxsl:node-set($entries)"/>

    <xsl:for-each select="$entryNodes">
        <xsl:value-of select="/root/name"/>
        <xsl:value-of select="."/>
    </xsl:for-each>

</xsl:template>

</xsl:stylesheet>

XML输入:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <name>X</name>
    <entry>1</entry>
    <entry>2</entry>
</root>

通缉输出:

X1X2

实际输出:

12

当然(或者)问题是副本,但是我无法解决这个问题。

3 个答案:

答案 0 :(得分:1)

  

我希望使用contains来构造一个XSL节点集变量   for-each loop。

我不知道这意味着什么。

  

构造的节点集是原始的(a   选择)节点集,而不是副本。

这部分我认为我明白了一点。看来你需要更换:

<xsl:variable name="entries">
    <xsl:for-each select="//entry">
        <xsl:copy-of select="."/>
    </xsl:for-each>
</xsl:variable>

使用:

<xsl:variable name="entries" select="//entry"/>

或者,最好是:

<xsl:variable name="entries" select="root/entry"/>

结果变量是原始entry节点的节点集,因此您只需执行以下操作:

<xsl:for-each select="$entries">
    <xsl:value-of select="/root/name"/>
    <xsl:value-of select="."/>
</xsl:for-each>

获得预期结果。

当然,您可以通过在原始节点上直接操作原始上下文来执行相同的操作 - 无需变量。


回应您的评论:

我们显然需要一个更好的例子,但我想我对你想要去哪里有一个模糊的想法。但是你必须先了解一些事情:

<强> 1
为了构造一个在原始上下文中包含节点的节点集的变量,必须使用select。这对您可以选择的内容没有任何限制。你可以一次完成所有选择,也可以分阶段进行选择,甚至可以循环进行选择(这里我指的是一个真正的循环)。您可以组合您以任何方式组合的中间选择组合:联合,交集或差异。但是你必须在所有这些步骤中使用select,否则你将得到一组新节点,不再具有他们在源树中所做的上下文。

IOW,使用copyselect之间的唯一区别是前者创建新节点,这正是您希望避免的。

<强> 2
xsl:for-each不是循环。它没有层次结构或年表。所有节点都是并行处理的,并且没有办法在当前节点中使用先前迭代的结果 - 因为没有迭代是&#34;之前的&#34;到另一个。

如果您尝试使用xsl:for-each将每个已处理的节点添加到预先存在的节点集中,您将得到n个结果,每个结果包含已连接的预先存在的节点集一个已处理的节点。

第3
我认为您会发现XPath语言非常强大,并且允许您选择所需的节点,而无需经历您提示的复杂循环。

答案 1 :(得分:1)

在XSLT 1.0中没有一种“解决方法” - 这正是它应该如何工作的。如果您有一个使用内容而不是select声明的变量,则该内容是由新创建的节点组成的结果树片段(即使这些节点是原始树中节点的副本)。如果要引用附加到原始树的原始节点,则必须使用select声明变量。更好的问题是详细说明实际问题并询问如何编写合适的select表达式来查找所需的节点而无需使用for-each - xsl:if或{的大多数用法{1}}可以用适当构造的谓词替换,可能涉及明智地使用xsl:choose等。


在XSLT 2.0中,它更加灵活。节点集和结果树片段之间没有区别,xsl:key的内容被视为通用的“序列构造函数”,如果您构造或复制它们,它们可以为您提供新节点:

xsl:variable

或原始节点(如果您使用<xsl:variable name="example" as="node()*"> <xsl:copy-of select="//entry" /> </xsl:variable>

xsl:sequence

答案 2 :(得分:0)

如果您向我们展示了一个在XSLT 1.0中无法轻易解决的问题,这可能会有所帮助。您无法按照要求的方式解决问题:在XSLT 1.0中没有等效的xsl:sequence。但是,如果没有这样的结构,你可以解决你向我们展示的问题。所以请解释为什么你需要你想要的东西。