根据属性值从xsl:key返回的包中删除重复项

时间:2014-05-21 14:34:33

标签: xslt xslt-1.0 duplicate-removal

我有以下xml文件。

<Bank>
  <Person personId="1" type="1071" deleted="0">
  </Person>
  <Person personId="2" type="1071" deleted="0">
  </Person>
  <Person personId="3" type="1071" deleted="0">
  </Person>
  <Account>
    <Role personId="1" type="1025" />
  </Account>
  <Account>
    <Role personId="1" type="1025" />
  </Account>
  <Account>
    <Role personId="1" type="1018" />
  </Account>
  <Account>
    <Role personId="3" type="1025" />
    <Role personId="1" type="1018" />
  </Account>
  <Account>
    <Role personId="2" type="1025" />
  </Account>
</Bank>

以及以下xsl转换。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="ISO-8859-1" />
  <xsl:strip-space elements="*" />

  <xsl:key name="roleKey"
    match="Role[(@type = '1025' or @type = '1018' or @type = '1022' or @type = '1023') and not(@validTo)]"
    use="@personId" />

  <xsl:template match="Person">
    <xsl:value-of select="@personId" />
    <xsl:variable name="roles" select="key('roleKey', @personId)" />
    <xsl:for-each select="$roles">
      <xsl:text>;</xsl:text><xsl:value-of select="@type" />
    </xsl:for-each>
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

实际结果如下,我想删除重复的type值。

1;1025;1025;1018;1018
2;1025
3;1025

预期结果应如下......

1;1025;1018
2;1025
3;1025

我尝试了this website中涉及关键字following的提示,以及Muenchian方法的技巧。它们都不起作用,因为它们似乎在浏览整个文档并匹配每个Person元素的重复项,而我只想在由{{1}定义的Person上下文中删除重复项属性。

如何从personId函数返回的包中删除这些重复项?或者也许我可以在key中使用一种方法来打印我想要的内容?

我只能使用XSLT 1.0中可用的内容。我没有办法使用任何XSLT 2.0处理器。

1 个答案:

答案 0 :(得分:1)

好的,不知道这是否是最好的解决方案,但我通过引入这样的密钥并使用Muenchian方法实现了我想要的目标。

<xsl:key name="typeKey" match="Role" use="concat(@type, '|', @personId)" />

改变后的整个转型看起来就像......

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="ISO-8859-1" />
  <xsl:strip-space elements="*" />

  <xsl:key name="roleKey"
    match="Role[(@type = '1025' or @type = '1018' or @type = '1022' or @type = '1023') and not(@validTo)]"
    use="@personId" />
  <xsl:key name="typeKey" match="Role" use="concat(@type, '|', @personId)" />

  <xsl:template match="Person">
    <xsl:value-of select="@personId" />
    <xsl:variable name="roles" select="key('roleKey', @personId)" />
    <xsl:for-each select="$roles[generate-id() = generate-id(key('typeKey', concat(@type, '|', @personId)))]">
      <xsl:text>;</xsl:text><xsl:value-of select="@type" />
    </xsl:for-each>
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

现在的结果是......

1;1025;1018
2;1025
3;1025