关于 xml:XSL 1.0 来自模板的不同值

 2022-01-07 

XSL 1.0 distinct values from a template

有人能帮我解决这个问题吗?

这是我的 XML -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<grandparent>
  <parent>
    <child>apple</child>
  </parent>
  <parent>
    <child>apple</child>
    <child>orange</child>
    <child>apple</child>
    <child>apple</child>
    <child>apple</child>
  </parent>
  <parent>
    <child>pear</child>
    <child>apple</child>
    <child>pear</child>
    <child>pear</child>
  </parent>
</granparent>

我有一个模板,我将父级传递给它并吐出所有子标签,但我希望它只吐出唯一的子值。

我四处搜索了一下,每个人关于使用密钥的建议似乎都不起作用,因为它似乎只能获取祖父范围内的唯一值,而不是父项范围内的唯一值.

这就是我所拥有的 -

1
2
3
4
5
6
7
<xsl:template name="uniqueChildren">
  <xsl:param name="parent" />

  <xsl:for-each select="$parent/child">
    <xsl:value-of select="." />
  </xsl:for-each>
</xsl:template>

当前显示 -

1
2
3
apple
apple orange apple apple apple
pear apple pear pear

我尝试按键时的代码 -

1
2
3
4
5
6
7
8
9
<xsl:key name="children" match="child" use="." />

<xsl:template name="uniqueChildren">
  <xsl:param name="parent" />

  <xsl:for-each select="$parent/child[generate-id() = generate-id(key('children', .)[1])]">
    <xsl:value-of select="." />
  </xsl:for-each>
</xsl:template>

当我尝试使用它显示的密钥时 -

1
2
3
apple
orange
pear

我想让它显示什么 -

1
2
3
apple
apple orange
pear apple


你对key方法非常接近,诀窍是你需要将父节点的身份作为分组键的一部分:

1
2
3
4
5
6
7
8
9
10
<xsl:key name="children" match="child" use="concat(generate-id(..), '|', .)" />

<xsl:template name="uniqueChildren">
  <xsl:param name="parent" />

  <xsl:for-each select="$parent/child[generate-id() = generate-id(
           key('children', concat(generate-id($parent), '|', .))[1])]"
>
    <xsl:value-of select="." />
  </xsl:for-each>
</xsl:template>

这会创建"<id-of-parent>|apple"、"<id-of-parent>|orange" 等形式的键值

编辑:在您的评论中,您说"在我的实际数据中,子节点不是父节点的直接子节点。父节点和子节点之间有 2 个级别,例如 parent/././child "

在这种情况下,原理相同,您只需要稍微调整一下键即可。关键是键值需要包含定义唯一性检查范围的节点的generate-id。因此,如果您知道您总是在 (parent/x/y/child) 之间恰好有两个级别,那么您将使用

1
2
<xsl:key name="children" match="child"
   use="concat(generate-id(../../..), '|', .)" />

或者如果 child 元素可能在 parent 中的不同级别,那么您可以使用类似

1
2
<xsl:key name="children" match="child"
   use="concat(generate-id(ancestor::parent[1]), '|', .)" />

(ancestor::parent[1] 是名称为 parent 的目标元素的最近祖先)