我应该如何在xslt中对数据进行分组?

时间:2019-04-03 07:59:55

标签: xslt xslt-1.0 xslt-grouping

我需要按时间段对历史记录进行分组,但是我无法执行此分组。 有人可以帮忙吗?我尝试使用xsl键,但其执行操作仅针对第一个响应。 您能否建议任何其他方法。有没有下面的预期输出所示的分组方法。

输入

php artisan passport:install

预期输出

<TEST>
     <RESPONSE>
        <NUMBER>XXXX</NUMBER>
        <HISTORY>
             <Period Year="2013" Month="Apr" Value="77"></Period>
             <Period Year="2013" Month="Mar" Value="99"></Period>
             <Period Year="2013" Month="Feb" Value="88"></Period>
             <Period Year="2012" Month="Jan" Value="11"></Period>
             <Period Year="2012" Month="Mar" Value="22"></Period>
             <Period Year="2011" Month="Apr" Value="444"></Period>
         </HISTORY>
     </RESPONSE>
     <RESPONSE>
        <NUMBER>ZZZZ</NUMBER>
        <HISTORY>
             <Period Year="2016" Month="Jan" Value="999"></Period>
             <Period Year="2016" Month="Mar" Value="454"></Period>
             <Period Year="2015" Month="Dec" Value="234"></Period>
             <Period Year="2014" Month="Jan" Value="767"></Period>
             <Period Year="2014" Month="Sep" Value="667"></Period>
             <Period Year="2013" Month="May" Value="112"></Period>
         </HISTORY>
     </RESPONSE>
</TEST>

样本xslt

<TEST>
     <RESPONSE>
        <NUMBER>XXXX</NUMBER>
        <HISTORY>
             <Period Year="2013" Month="Apr" Value="77"></Period>
             <Period Year="2013" Month="Mar" Value="99"></Period>
             <Period Year="2013" Month="Feb" Value="88"></Period>
             <Period Year="2012" Month="Jan" Value="11"></Period>
             <Period Year="2012" Month="Mar" Value="22"></Period>
             <Period Year="2011" Month="Apr" Value="444"></Period>
         </HISTORY>
         <GROUP-HISTORY>
                <YEAR Value="2013">
                        <Months Month="Apr" Value="77"/>
                        <Months Month="Mar" Value="99"/>
                        <Months Month="Feb" Value="88"/>
                </YEAR>
                <YEAR Value="2012">
                        <Months Month="Jan" Value="11"/>
                        <Months Month="Mar" Value="22"/>
                </YEAR>
                <YEAR Value="2011">
                        <Months Month="Apr" Value="444"/>       
                </YEAR>
         </GROUP-HISTORY>
     </RESPONSE>
     <RESPONSE>
        <NUMBER>ZZZZ</NUMBER>
        <HISTORY>
             <Period Year="2016" Month="Jan" Value="999"></Period>
             <Period Year="2016" Month="Mar" Value="454"></Period>
             <Period Year="2015" Month="Dec" Value="234"></Period>
             <Period Year="2014" Month="Jan" Value="767"></Period>
             <Period Year="2014" Month="Sep" Value="667"></Period>
             <Period Year="2013" Month="May" Value="112"></Period>
         </HISTORY>
         <GROUP-HISTORY>
                <YEAR Value="2016">
                        <Months Month="Jan" Value="999"/>
                        <Months Month="Mar" Value="454"/>   
                </YEAR>
                <YEAR Value="2015">
                        <Months Month="Dec" Value="234"/>       
                </YEAR>
                <YEAR Value="2014">
                        <Months Month="Jan" Value="767"/>   
                        <Months Month="Sep" Value="667"/>                               
                </YEAR>
                <YEAR Value="2013">
                        <Months Month="May" Value="112"/>       
                </YEAR>
         </GROUP-HISTORY>
     </RESPONSE>
</TEST>

1 个答案:

答案 0 :(得分:1)

主要问题是您需要在密钥中说明NUMBER,否则您将在整个文档中对所有匹配的年份进行分组

<xsl:key name="years" match="Period" use="concat(../../NUMBER, '|', @Year)"/>

此外,对于您的第一个xsl:for-each,您可以从/TEST/RESPONSE/HISTORY/Period开始选择表达式,当您确实需要相对于当前{{1 }},就像这样:

HISTORY

尝试使用此XSLT

<xsl:for-each select="Period[generate-id(.) = generate-id(key('years', concat(../../NUMBER, '|', @Year))[1])]">

请注意:

  1. 您无需在<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:key name="years" match="Period" use="concat(../../NUMBER, '|', @Year)"/> <xsl:template match="node() | @*" name="identity"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <xsl:template match="HISTORY"> <xsl:call-template name="identity" /> <GROUP-HISTORY> <xsl:for-each select="Period[generate-id(.) = generate-id(key('years', concat(../../NUMBER, '|', @Year))[1])]"> <xsl:sort select="@Year" order="descending"/> <xsl:variable name="currY" select="@Year"/> <Year Value="{$currY}"> <xsl:for-each select="key('years', concat(../../NUMBER, '|', $currY))"> <Months Month="{@Month}" Value="{@Value}" /> </xsl:for-each> </Year> </xsl:for-each> </GROUP-HISTORY> </xsl:template> </xsl:stylesheet> 中指定匹配元素的完整路径(除非您有其他名称相同但不想匹配的路径,否则不需要)。
  2. 您不需要匹配xsl:key的模板,因为身份模板会做同样的事情。
  3. 如果元素名称是静态的,则无需使用TEST。只需直接写出元素标签即可。
  4. 您可以使用Attribute Value Templates简化属性的创建。