0

您好,关于stackoverflow的第一个问题:-)

我在使用 XSLT 中的 xsl:key 函数时遇到了一种奇怪的行为,这有点难以解释,但很容易演示。

当我使用 xsl:key 元素索引 2 个不同但完全相同的节点集时,它无法正确索引它们。

在这个测试示例中,我想知道每个表有多少个单元格被索引。这是我的第一个输入,包含 2 个完全相同的表(@id 除外):

<?xml version="1.0" encoding="UTF-8"?>
<test>
    <table id="table1">
        <cell>Cell 1</cell>
        <cell>Cell 2</cell>
        <cell>Cell 3</cell>
    </table>
    <table id="table2">
        <cell>Cell 1</cell>
        <cell>Cell 2</cell>
        <cell>Cell 3</cell>
    </table>
</test>

然后我的第二个输入与第二个表的内容略有不同(第一个单元格包含带有下划线的“cell_1”):

<?xml version="1.0" encoding="UTF-8"?>
<test>
    <table id="table1">
        <cell>Cell 1</cell>
        <cell>Cell 2</cell>
        <cell>Cell 3</cell>
    </table>
    <table id="table2">
        <cell>Cell_1</cell>
        <cell>Cell 2</cell>
        <cell>Cell 3</cell>
    </table>
</test>

这是我的 XSLT。我正在计算每个表格元素,共享相同当前 parent::table 的单元格的数量。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

    <xsl:key name="cell" match="//cell" use="parent::table"/>

    <xsl:template match="//test">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="table">
        <numcells id_table="{@id}">
            <xsl:value-of select="count(key('cell', .))"/>
        </numcells>
    </xsl:template>

</xsl:stylesheet>

这是带有 2 个相同表格的第一个输出。它在每个表格中显示 6 个单元格,而不是 3 个。

<?xml version="1.0" encoding="utf-8"?>
<test>
    <numcells id_table="table1">6</numcells>
    <numcells id_table="table2">6</numcells>
</test>

现在第二个输出有 2 个不同的表。它为每个表格显示了正确数量的 3 个单元格。

<?xml version="1.0" encoding="utf-8"?>
<test>
    <numcells id_table="table1">3</numcells>
    <numcells id_table="table2">3</numcells>
</test>

它可能与 XSLT 处理器有关,但我已经用 Saxon、Xalan 和 XSLTProc 对其进行了测试,结果相同。

我已经看到我可以通过使用@id 来解决这个问题:

<xsl:key name="cell" match="//cell" use="parent::table/@id"/>

进而:

<xsl:value-of select="count(key('cell', @id))"/>

但我仍然想知道是什么导致了这种行为。感谢您的解释!

4

1 回答 1

1

键值是一个原始值,如字符串或数字,而不是节点本身。如果要键入节点身份,请使用use="generate-id(parent::table)".

您当前的键是table元素的字符串值,这是所有文本后代节点的串联,因此对于第一个示例,您会获得键值,例如

Cell 1
Cell 2
Cell 3

您希望根据节点的身份进行分组或键入,而不是根据其字符串内容。因此,正如您已经发现的那样,使用generate-id或使用元素id上存在的属性。table

于 2013-07-19T11:23:20.587 回答