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

标签 xslt xpath xslt-2.0

需要明确的是,我已经找到了一种使用 XSLT 来完成我想要的任务的方法,但它让我觉得效率很低,我想看看是否可以使用不同的解决方案,因为它有助于写作 future 的样式表。

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

至少,我试图从用俄语编写并用 XML 编码的故事中提取数据(“pavlova.xml” - 不幸的是,文件太大,无法与我的问题一起发布,但它不是完全必要的)数据对于在 SVG 中生成饼图很有用。我试图将这些数据存储在名为 $chartData 的变量中。给定的饼图总体上属于目标角色(参数),饼图的每个单独 block 将代表一个说话者(另一个角色),它们的大小指示每个说话者相对于其他说话者谈论目标角色的程度。我首先迭代所有说话者(任何曾经提到过目标角色的角色),然后确定该角色的名字在特定说话者的讲话中出现的次数。然而,这些值仅对于角色被提及的总次数有用。我需要总数来计算生成饼图的百分比。我知道我可以在另一个变量中单独计算它,但我有兴趣看看是否可以在变量中存储节点序列。单独计算总和似乎很浪费,因为它遍历的路径与查找各个计数的路径几乎相同,在检索各个值后对各个值求和会更有效。到目前为止,我已经能够计算我想要的所有内容,但我尝试使用 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,而不是声明变量并使用 xsl:copy-在外部 for-each 中将数据附加到变量)。

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

最终目标是使底部注释掉的 for-each 循环迭代每个计数元素,而不是给我一个错误。我的问题是,我可以将变量视为 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>

如果是这样,怎么办?

此外,如果有人可以解释一下,为什么当我将 for-each 置于变量范围之外并将 select 设置为“$chartData”时,为什么 xsl:copy-of 只进行深层复制?如果我尝试在变量中使用 xsl:copy-of ,它只会复制文字 <count> 的文本内容元素并创建一个字符串:424341326206641511313)。

最佳答案

恐怕你的问题很令人困惑。您想要做的事情并不困难,但很难知道从哪里开始帮助您前进。

I am interested in seeing if I can store a sequence of nodes in a variable

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

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

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

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

<xsl:variable name="seq" as="node()*">
  ... content ...
</xsl:variable>

I am trying instead to iterate over a variable using an xsl:for-each and have it recognize my variable as a sequence

好吧,每个变量的值都是一个序列,问题是,序列中是什么?如果您使用上面变量的第一种形式(内容,无属性),则序列将是包含单个文档节点的单例序列;您可能希望使用路径表达式导航到其子级,例如 <xsl:for-each select="$tree/*"/> 。在第二种和第三种情况下,序列通常包含多个节点,这些节点可以是任何类型的节点,因此您更有可能编写 <xsl:for-each select="$seq"/> .

I'm finding it difficult to locate and comprehend documentation on that attribute and how SequenceType's work

你在哪里看的?我怎么推荐我的书“XSLT 2.0 程序员引用”都不过分...... 我认为你是那种想要了解事物真正如何运作的人,而不是通过实例中的反复试验来学习。这本书就是为这类人写的。

It seems that xsl:copy-of, as opposed to xsl:sequence (ironically) is what I need to append a sequence of nodes.

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

can I treat a variable as XML and iterate over each count element if it looks like the following

是的,你可以。但我们无法从序列的表示中判断这些节点是否是文档节点的子节点,了解这一点至关重要。

why does xsl:copy-of only deep-copy when I have the for-each outside of the variable's scope and set select to '$chartData'? If I try to use xsl:copy-of within the variable it only copies the text content of the literal elements and creates a string

您在这里得出了错误的推论。 xsl:copy-of 始终执行深层复制。如果您只看到节点的字符串内容,那是因为正在使用后续操作来原子化节点或提取其字符串值。

关于xslt - 在 XSLT 变量中构造 XML 元素序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11533326/

相关文章:

xslt - 使用 XSLT 1.0 将元素连接行和列名称的平面 XML 表数据转换为嵌套的 XML

字符串中每个字母的 XSLT

xml - 如何在 XSLT2 replace() 函数中转换 'mix and match' 实体?

xslt-2.0 - xslt : keeping namespace declaration on root when root element is not known in advance

xml - 比价网站 - 它们如何运作?

javascript - 在具有某些参数的 xsl 中调用 javascript 函数

Python XPath 语法错误 : invalid predicate

python-3.x - 使用 Selenium 抓取(Python)时只有第一行

xslt - 使用 XSL 定义特定元素的缩进

xslt - Saxon Transformerfactory 放置不需要的 xmlns :xsd ="http://www.w3.org/2001/XMLSchema" in transformer output