使用 muenchian 分组 select 子树中的不同值

Using muenchian grouping to select distinct values in a subtree

我知道如何进行 muenchian 分组,但这通常应用于整个文档 (?)。

这里我想在子树中找到不同的值。

例如

<root>
  <parent>
    <child id="1"/>
    <child id="1"/>
    <child id="2"/>
  </parent>
  <parent>
    <child id="2"/>
    <child id="3"/>
    <child id="3"/>
  </parent>
</root>

我想映射到

<root>
  <parent>
    <child id="1"/>
    <child id="2"/>
  </parent>
  <parent>
    <child id="2"/>
    <child id="3"/>
  </parent>
</root>

如果我尝试

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

  <xsl:key name="id_to_id" match="/root/parent/child" use="@id"/>
  
    <xsl:template match="/root">
      <root>
        <xsl:for-each select="parent">
          <parent>
            <xsl:for-each select="child[generate-id() = generate-id(key('id_to_id',@id)[1])]">
              <child id="{@id}"/>
            </xsl:for-each>            
          </parent>       
        </xsl:for-each>
      </root>
    </xsl:template>
</xsl:stylesheet>

然后它对整个文档进行密钥处理,我得到

<root>
  <parent>
    <child id="1" />
    <child id="2" />
  </parent>
  <parent>
    <child id="3" />
  </parent>
</root>

所以实际上我刚刚创建了一个解决方案,但它有点奇怪,即为父节点生成一个 id,实际上我们有一个 id 属性 + 节点 id 的复合键

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

  <xsl:key name="id_to_id" match="/root/parent/child" use="concat(@id,'|',generate-id(..))"/>
  
    <xsl:template match="/root">
      <root>
        <xsl:for-each select="parent">
          <parent>
            <xsl:for-each select="child[generate-id() = generate-id(key('id_to_id',concat(@id,'|',generate-id(..)))[1])]">
              <child id="{@id}"/>
            </xsl:for-each>            
          </parent>       
        </xsl:for-each>
      </root>
    </xsl:template>
</xsl:stylesheet>

这是做这类事情的标准方法吗?

这是另一个同样奇怪的解决方案,仍然不确定这是否非常明智,是否有某种 XPath 括号或我可以使用的东西?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

  <xsl:key name="id_to_id" match="child" use="@id"/>
  
    <xsl:template match="/root">
      <root>
        <xsl:for-each select="parent">
          <parent>
            <xsl:variable name="children">
              <xsl:copy-of select="child"/>
            </xsl:variable>
            <xsl:for-each select="msxsl:node-set($children)/child[generate-id() = generate-id(key('id_to_id',@id)[1])]">
              <child id="{@id}"/>
            </xsl:for-each>            
          </parent>       
        </xsl:for-each>
      </root>
    </xsl:template>
</xsl:stylesheet>

现在没有 muenchian 分组(这不是我想要的,但它是一种很好的声明方法),除了一小群兄弟姐妹之外不适合任何东西。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/root">
      <root>
        <xsl:for-each select="parent">
          <parent>
            <xsl:for-each select="child[not(@id = preceding-sibling::child/@id)]">
              <child id="{@id}"/>
            </xsl:for-each>            
          </parent>       
        </xsl:for-each>
      </root>
    </xsl:template>
</xsl:stylesheet>