【问题标题】:Finding Duplicates with xsl:key?使用 xsl:key 查找重复项?
【发布时间】:2022-01-02 06:57:04
【问题描述】:

以下代码用于输出在其他组中找到的“g”中的行李编号。有什么方法可以使用xsl:key 达到同样的效果吗?理想情况下,“g”将是一个参数,因此我不必为“h”、“i”等重复类似的代码。

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <g>
        <bagn>A</bagn>
        <bagn>B</bagn>
    </g>
    <h>
        <bagn>C</bagn>
        <bagn>D</bagn>
        <bagn>A</bagn>
    </h>
    <i>
        <bagn>B</bagn>
        <bagn>F</bagn>
        <bagn>G</bagn>
    </i>
</root>
         <xsl:variable name="gDups">
            <xsl:for-each select="/root/g/bagn[.=/root/node()[not(self::g)]/bagn]">
               <xsl:choose>
                  <xsl:when test="position()=1">
                     <xsl:value-of select="concat('|',.,'|')"/>
                  </xsl:when>
                  <xsl:otherwise>
                     <xsl:value-of select="concat(.,'|')"/>
                  </xsl:otherwise>
               </xsl:choose>
            </xsl:for-each>
         </xsl:variable>
         
         <xsl:value-of select="$gDups"/>

【问题讨论】:

  • 您是否看过 XSLT 中的键简介并尝试一下?至于使用g 的参数,还请告诉我们您使用的是哪个版本的 XSLT 和/或哪个 XSLT 处理器。
  • 我正在为 Xalan 使用 XSLT 版本 1
  • 您打算如何传递参数?作为包含元素名称的字符串?可以有两个同名的兄弟元素吗?
  • 我不知道是否可以将其作为参数传递。这是我的问题的一部分。
  • 你想要的结果是什么?为root 的每个孩子生成重复列表并不难。

标签: xml xslt


【解决方案1】:

考虑以下示例:

XSLT 1.0

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

<xsl:key name="bagn" match="bagn" use="." />

<xsl:template match="/root">
    <duplicates>
        <xsl:for-each select="*">
            <!-- duplicates in siblings -->
            <xsl:variable name="dups" select="key('bagn', bagn)[not(generate-id(..) = generate-id(current()))]" />
            <xsl:if test="$dups">
                <xsl:copy>
                    <xsl:for-each select="$dups">
                        <xsl:value-of select="."/>
                        <xsl:if test="position()!=last()">|</xsl:if>
                    </xsl:for-each>
                </xsl:copy>
            </xsl:if>
        </xsl:for-each>
    </duplicates>
</xsl:template>

</xsl:stylesheet>

应用于您的示例输入,这将返回:

结果

<?xml version="1.0" encoding="UTF-8"?>
<duplicates>
  <g>A|B</g>
  <h>A</h>
  <i>B</i>
</duplicates>

请注意,这会返回其他兄弟姐妹中的重复项列表,即使兄弟姐妹具有相同的名称。例如,对于输入:

<root>
    <g>
        <bagn>A</bagn>
        <bagn>B</bagn>
    </g>
    <g>
        <bagn>C</bagn>
        <bagn>D</bagn>
        <bagn>A</bagn>
    </g>
    <g>
        <bagn>B</bagn>
        <bagn>F</bagn>
        <bagn>G</bagn>
    </g>
</root>

结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<duplicates>
  <g>A|B</g>
  <g>A</g>
  <g>B</g>
</duplicates>

【讨论】:

  • “即使兄弟姐妹同名”,明白了。谢谢。
  • 您的问题得到解答了吗?
  • 是的,我正在花时间消化它,因为它有两个我几乎没有使用过的概念:key 和 generate-id 并且您正在以非常非正统的方式使用它......至少为了我。非常感谢。我想知道在这种情况下是否真的需要密钥,或者是否必须获得该结果。
  • 它可以在没有密钥的情况下完成(我认为),但密钥是解决交叉引用的最佳方式。即使您的问题没有提及,我也会使用它。
  • 另外,使用 generate-id() 来确定两个节点是否相同也很常见(c.f. jenitennison.com/xslt/grouping/muenchian.html)。在 Xalan 中,您还可以为此目的利用一些扩展功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多