使用 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>
我知道如何进行 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>