XSLT组在多个键上



这是输入文件。

<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>

分组规则

  • 价格
  • 腿group=0, groupp =1为对。当leg group =0具有group =1中相同的Key=时,我们可以对leg进行分组。例如,Group=0中的Leg有Key=56T58T, Group=1中有两个Key (177T179T和196T198T)。相同的两个键(177T179T和196T198T)的Leg in Group=0 Key=128T130T。我们可以写入分组
    <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,但它只按Price

    分组

    <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>
    

    任何帮助都将非常感激。

    Step by Step分组

    1. 按相同的Price和Key为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>

    2. 在每个组中删除重复的腿(相同的键)

      <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>

    3. 组相同的价格和相同的键为Leg Group=1(第一组和第二组有相同的Leg Group=1,所以我们可以称之为Group)

      <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>

    4. 在每个组中删除重复的腿(相同的键)

      <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>

    最后是输出

  • 为了推进这一进程,我发布了这个暂定的样式表,它可能接近也可能不接近你想要的:

    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>
    

    有趣的分配…

    我认为答案在Muenchian Grouping中并不像在递归中那么多。您可以遵循第一个组的引用路径,并注册所遵循路径的key在对特定路径的所有Leg元素进行分组之后,您可以移动到下一个尚未"访问"的Box,以创建下一个组

    <?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>
    

    相关内容

    • 没有找到相关文章

    最新更新