这是输入文件。
<XML>
<Box Price="541" Key="1">
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
</Box>
<Box Price="541" Key="2">
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
</Box>
<Box Price="541" Key="3">
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
</Box>
<Box Price="541" Key="4">
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
</Box>
<Box Price="541" Key="5">
<Leg Key="243T246T" Group="0"></Leg>
<Leg Key="60T63T" Group="1"></Leg>
</Box>
<Box Price="541" Key="6">
<Leg Key="243T246T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Box>
<Box Price="700" Key="7">
<Leg Key="243T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Box>
</XML>
输出结果为:
<Box Price="541">
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
</Box>
<Box Price="541">
<Leg Key="243T246T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
<Leg Key="60T63T" Group="1"></Leg>
</Box>
<Box Price="700">
<Leg Key="243T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Box>
分组规则
<Box Price="541">
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
</Box>
我正在使用XSLT 1.0。任何帮助都会非常感激。
我有xsl,但它只按价格分组
<xsl:output method="xml" indent="yes" />
<xsl:key name="price" match="Box" use="@Price" />
<xsl:template match="XML">
<xsl:apply-templates select="Box[generate-id(.)=generate-id(key('price',@Price)[1])]"/>
</xsl:template>
<xsl:template match="Box">
<Group Price="{@Price}">
<xsl:for-each select="key('price', @Price)">
<xsl:for-each select="Leg">
<Leg Key="{@Key}" Group="{@Group}"></Leg>
</xsl:for-each>
</xsl:for-each>
</Group>
</xsl:template>
和输出:
<?xml version="1.0"?>
<Group Price="541">
<Leg Key="56T58T" Group="0"/>
<Leg Key="177T179T" Group="1"/>
<Leg Key="128T130T" Group="0"/>
<Leg Key="196T198T" Group="1"/>
<Leg Key="56T58T" Group="0"/>
<Leg Key="196T198T" Group="1"/>
<Leg Key="128T130T" Group="0"/>
<Leg Key="177T179T" Group="1"/>
<Leg Key="243T246T" Group="0"/>
<Leg Key="60T63T" Group="1"/>
<Leg Key="243T246T" Group="0"/>
<Leg Key="133T136T" Group="1"/>
</Group><Group Price="700">
<Leg Key="243T" Group="0"/>
<Leg Key="133T136T" Group="1"/>
</Group>
任何帮助都会非常感激。
逐步分组。
按相同价格分组并且Leg Group的相同键= 0
<Group Price="541">
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
</Group>
<Group Price="541">
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
</Group>
<Group Price="541">
<Leg Key="243T246T" Group="0"></Leg>
<Leg Key="60T63T" Group="1"></Leg>
<Leg Key="243T246T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Group>
<Group Price="700">
<Leg Key="243T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Group>
在每个组中删除重复的Legs(相同的Key)
<Group Price="541" >
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
</Group>
<Group Price="541">
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
</Group>
<Group Price="541">
<Leg Key="243T246T" Group="0"></Leg>
<Leg Key="60T63T" Group="1"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Group>
<Group Price="700">
<Leg Key="243T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Group>
将Leg Group的相同价格和相同的密钥分组= 1(首先是第二组具有相同的Legs组= 1,所以我们可以Gruop)
<Group Price="541">
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
</Group>
<Group Price="541">
<Leg Key="243T246T" Group="0"></Leg>
<Leg Key="60T63T" Group="1"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Group>
<Group Price="700">
<Leg Key="243T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Group>
在每个组中删除重复的Legs(相同的Key)
<Group Price="541">
<Leg Key="56T58T" Group="0"></Leg>
<Leg Key="128T130T" Group="0"></Leg>
<Leg Key="177T179T" Group="1"></Leg>
<Leg Key="196T198T" Group="1"></Leg>
</Group>
<Group Price="541">
<Leg Key="243T246T" Group="0"></Leg>
<Leg Key="60T63T" Group="1"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Group>
<Group Price="700">
<Leg Key="243T" Group="0"></Leg>
<Leg Key="133T136T" Group="1"></Leg>
</Group>
最终是它的输出。
答案 0 :(得分: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="box-by-price" match="Box" use="@Price" />
<xsl:key name="box-by-legs" match="Box" use="Leg/@Key" />
<xsl:key name="leg-by-key" match="Leg" use="@Key" />
<xsl:template match="XML">
<root>
<!-- (1) group by price -->
<xsl:for-each select="Box[generate-id()=generate-id(key('box-by-price',@Price)[1])]">
<!-- (2) within each price group, combine boxes that share a common leg (regardless of group) -->
<xsl:for-each select="key('box-by-price',@Price)[generate-id()=generate-id(key('box-by-legs',Leg/@Key)[1])]">
<Group Price="{@Price}">
<!-- (3) in each group, list the unique legs of all the boxes in the group -->
<xsl:copy-of select="key('box-by-legs',Leg/@Key)/Leg[generate-id()=generate-id(key('leg-by-key',@Key)[1])]"/>
</Group>
</xsl:for-each>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
当此功能应用于输入:
时<?xml version="1.0" encoding="UTF-8"?>
<XML>
<Box Price="541" Key="1">
<Leg Key="56T58T" Group="0"/>
<Leg Key="177T179T" Group="1"/>
</Box>
<Box Price="541" Key="2">
<Leg Key="128T130T" Group="0"/>
<Leg Key="196T198T" Group="1"/>
</Box>
<Box Price="541" Key="3">
<Leg Key="56T58T" Group="0"/>
<Leg Key="196T198T" Group="1"/>
</Box>
<Box Price="541" Key="4">
<Leg Key="128T130T" Group="0"/>
<Leg Key="177T179T" Group="1"/>
</Box>
<Box Price="541" Key="5">
<Leg Key="243T246T" Group="0"/>
<Leg Key="60T63T" Group="1"/>
</Box>
<Box Price="541" Key="6">
<Leg Key="243T246T" Group="0"/>
<Leg Key="133T136T" Group="1"/>
</Box>
<Box Price="700" Key="7">
<Leg Key="243T" Group="0"/>
<Leg Key="133T136T" Group="1"/>
</Box>
</XML>
结果是:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<Group Price="541">
<Leg Key="56T58T" Group="0"/>
<Leg Key="177T179T" Group="1"/>
</Group>
<Group Price="541">
<Leg Key="128T130T" Group="0"/>
<Leg Key="196T198T" Group="1"/>
</Group>
<Group Price="541">
<Leg Key="243T246T" Group="0"/>
<Leg Key="60T63T" Group="1"/>
<Leg Key="133T136T" Group="1"/>
</Group>
</root>
答案 1 :(得分:0)
有趣的作业......
我认为答案在Muenchian Grouping中并不像递归那样多。 您可以按照第一组的引用路径并注册所遵循的路径的键 在对该特定路径的所有Leg元素进行分组之后,您可以继续前进到尚未访问的下一个Box&#34;创建下一组
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="link" match="Leg" use="concat(parent::Box/@Price, '-', @Key, '-', @Group)"/>
<xsl:output indent="yes"/>
<xsl:template match="XML">
<XML>
<xsl:call-template name="process-group-node">
<xsl:with-param name="box" select="Box[1]"/>
</xsl:call-template>
</XML>
</xsl:template>
<xsl:template name="process-group-node">
<xsl:param name="box"/>
<xsl:param name="used-keys"/>
<xsl:variable name="new-keys">
<xsl:call-template name="search-path">
<xsl:with-param name="running-route" select="'#'"/>
<xsl:with-param name="current-leg" select="$box/Leg[1]"/>
</xsl:call-template>
</xsl:variable>
<Box Price="{$box/@Price}">
<xsl:for-each select="/XML/Box[contains($new-keys, concat('#', @Key, '#'))]/Leg[generate-id() = generate-id(key('link', concat(parent::Box/@Price, '-', @Key, '-', @Group) )[1])]">
<xsl:sort select="@Group" data-type="number" order="ascending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</Box>
<xsl:variable name="new-concat-keys" select="concat($used-keys, $new-keys)"/>
<xsl:if test="$box/following-sibling::Box[not(contains($new-concat-keys, concat('#', @Key, '#')))]">
<xsl:call-template name="process-group-node">
<xsl:with-param name="box" select="$box/following-sibling::Box[not(contains($new-concat-keys, concat('#', @Key, '#')))]"/>
<xsl:with-param name="used-keys" select="$new-concat-keys"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="search-path">
<xsl:param name="running-route"/>
<xsl:param name="current-leg"/>
<xsl:choose>
<xsl:when test="contains($running-route, concat('#', $current-leg/parent::Box/@Key, '#'))">
<xsl:value-of select="$running-route"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="this-id" select="generate-id($current-leg)"/>
<xsl:variable name="this-key" select="concat($current-leg/parent::Box/@Price, '-', $current-leg/@Key, '-', $current-leg/@Group)"/>
<xsl:variable name="next-equivalent-leg" select="key('link', $this-key)[not(generate-id() = $this-id)]"/>
<xsl:variable name="next-equivalent-id" select="generate-id($next-equivalent-leg)"/>
<xsl:variable name="next-leg" select="$next-equivalent-leg/parent::Box/Leg[not(generate-id() = $next-equivalent-id)]"/>
<xsl:call-template name="search-path">
<xsl:with-param name="running-route" select="concat($running-route, $current-leg/parent::Box/@Key ,'#')"/>
<xsl:with-param name="current-leg" select="$next-leg"></xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>