0

这是输入文件。

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

分组规则

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

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

    任何帮助将不胜感激。

    逐步分组。

    1. 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 分组相同的价格和相同的键(第一个和第二个组具有相同的 Legs Group=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>

    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>

    最后它的输出。

  • 4

    2 回答 2

    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>
    
    于 2014-05-14T13:30:38.080 回答
    0

    有趣的任务...

    我认为答案在 Muenchian Grouping 中不如在递归中那么多。您可以遵循第一组的引用路径并注册所遵循路径的键在您为该特定路径分组所有 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>
    
    于 2014-05-21T09:35:17.090 回答