在XSLT变量中构造XML元素序列

在XSLT变量中构造XML元素序列,xslt,xpath,xslt-2.0,Xslt,Xpath,Xslt 2.0,说得清楚一点,我已经找到了一种使用XSLT实现我想要实现的目标的方法,但我觉得这在很大程度上是低效的,我想看看是否有可能使用另一种解决方案,因为它将有助于编写未来的样式表 此外,我对以下段落的冗长表示诚挚的歉意 至少,我试图从一篇用俄语编写并用XML编码的故事中提取数据(“pavlova.XML”-不幸的是,文件太大,无法用我的问题发布,但并非完全必要),这些数据对于在SVG中生成饼图非常有用。我试图将这些数据存储在一个名为$chartData的变量中。给定的饼图总体上与目标角色(一个参数)相关

说得清楚一点,我已经找到了一种使用XSLT实现我想要实现的目标的方法,但我觉得这在很大程度上是低效的,我想看看是否有可能使用另一种解决方案,因为它将有助于编写未来的样式表

此外,我对以下段落的冗长表示诚挚的歉意

至少,我试图从一篇用俄语编写并用XML编码的故事中提取数据(“pavlova.XML”-不幸的是,文件太大,无法用我的问题发布,但并非完全必要),这些数据对于在SVG中生成饼图非常有用。我试图将这些数据存储在一个名为$chartData的变量中。给定的饼图总体上与目标角色(一个参数)相关,饼图的每个单独块将表示一个说话人(另一个角色),其大小指示每个说话人相对于其他说话人谈到目标角色的程度。我首先迭代所有演讲者(任何提到目标角色的角色),然后确定角色的名字在特定演讲者的演讲中出现的次数。但是,这些值仅在涉及角色的总次数时有用。我需要总数来计算百分比以生成饼图。我知道我可以在另一个变量中单独计算,但我想看看是否可以在一个变量中存储一系列节点。单独计算总和似乎很浪费,因为它所经过的路径与查找单个计数的路径几乎相同,在检索到单个值后,只求和会更有效。到目前为止,我已经能够计算出我想要的所有内容,但我尝试使用xsl:for-each对变量进行迭代,并让它将我的变量识别为序列

我希望变量的格式如下:

<count name="$speaker1>
    <xsl:value-of select="$spokenCount1"/>
</count>
<count name="$speaker2>
    <xsl:value-of select="$spokenCount2"/>
</count>
...

...
我已经尝试了很多方法来解决这个问题,但我不确定是否有可能解决。首先是通过使用@as属性更准确地定义xsl:variable的内容(具体地说,尝试将其内容定义为序列),但我发现很难找到和理解关于该属性的文档以及SequenceType的工作方式。其次,我尝试了如何将内容放入变量中(直接将for-each放在变量中,使用xsl:value of或xsl:copy of,而不是在外部for-each中声明变量并使用xsl:copy of将数据附加到变量)

似乎xsl:copy of,而不是xsl:sequence(讽刺的是)是我需要附加一个节点序列的东西。我只能通过以下代码获得上述格式:

<xsl:variable name="chartData"/>
    <xsl:for-each
        select="distinct-values(//speech[.//name[not(parent::nonspeech) and ./@ref eq $character]]/@speaker)">
        <xsl:copy-of select="$chartData"/>
        <xsl:variable name="speaker" select="current()"/>
        <xsl:variable name="spokenCount"
            select="document('pavlova.xml')/count(//speech[@speaker eq $speaker]//name[not(parent::nonspeech) and ./@ref eq $character])"/>
        <count name="{$speaker}">
            <xsl:value-of select="$spokenCount"/>
        </count>
    </xsl:for-each>
    <xsl:variable name="spokenTotal" select="sum($chartData)"/>
    <xsl:value-of select="$chartData"/>
    <!--xsl:for-each select="$chartData/count">
        ...
    </xsl:for-each-->

最终的目标是让底部的每个循环的注释都遍历每个count元素,而不是给我一个错误。我的问题是,如果变量如下所示,我可以将其视为XML并迭代每个计数元素,还是始终将其视为字符串

<?xml version="1.0" encoding="UTF-8"?>
<count name="young-man">4</count>
<count name="olga">24</count>
<count name="cecilija">34</count>
<count name="blonde">1</count>
<count name="vera">32</count>
<count name="servant-fem">6</count>
<count name="valickaja">20</count>
<count name="muse">66</count>
<count name="viktor">4</count>
<count name="dmitrij">15</count>
<count name="anna">11</count>
<count name="iličev">3</count>
<count name="narod">1</count>
<count name="society-man">3</count>

4.
24
34
1.
32
6.
20
66
4.
15
11
3.
1.
3.
如果是,怎么做


另外,如果有人可以解释,为什么xsl:copy-of-only-deep-copy在变量的作用域之外有for-each并将select设置为“$chartData”?如果我尝试在变量中使用xsl:copy of,它只会复制literal
元素的文本内容,并创建一个字符串:42434132606641511313)。

恐怕您的问题非常混乱。你想做的并不困难,但很难知道从哪里开始帮助你前进

我感兴趣的是看我是否可以在变量中存储一系列节点

是的,你可以。您需要清楚地知道是要创建新节点,还是希望变量保存对现有节点的引用。在第一种情况下,使用“临时树”构造:

<xsl:variable name="tree">
  ... content ...
</xsl:variable>

... 内容。。。
在第二种情况下,您可以使用select属性,也可以使用包含的序列构造函数加上“as”属性:

<xsl:variable name="seq" select="expression"/>


... 内容。。。
相反,我尝试使用xsl:for-each对变量进行迭代,并让它将我的变量识别为序列

每个变量的值都是一个序列,问题是,序列中有什么?如果使用上述变量的第一种形式(content,no-as属性),则序列将是包含单个文档节点的单例序列;您可能希望使用路径表达式导航到其子级,例如
。在第二种和第三种情况下,序列通常包含多个节点,这些节点可以是任何类型的节点,因此您更有可能编写

我发现很难找到和理解关于该属性的文档以及SequenceType是如何工作的

你在哪里找的?我不能过分推荐我的书“XSLT2.0程序员参考”。。。 我认为你是那种想了解事情是如何运作的人,而不是从例子中反复学习。这本书是为那种人写的

似乎xsl:copy of,而不是xsl:sequence(讽刺的是)是我需要附加一个节点序列的东西

不,你搞错了。如果要创建包含对现有节点的引用的变量,则需要xsl:sequence。如果要创建包含节点副本的临时树,则xsl:sequence和xsl:copy of具有完全相同的效果—两者都将复制选定的节点

如果变量如下所示,是否可以将其视为XML并迭代每个计数元素

是的,你可以。但我们不能从你的代表那里看出
<xsl:variable name="seq" as="node()*">
  ... content ...
</xsl:variable>