XSLT Munchen方法和先前XML标记的子元素

时间:2016-03-28 16:15:26

标签: xslt

我一直试图将数据分组以减少输出,但是当我使用Munchen时,我接近我想要的东西,但是有了预期的"错误"在输出中。我试图想出一个解决方案,但我已经没有想法了!

请注意,此处设置的数据是非常简化实际数据,以便能够发布此问题。在真实数据中,不同级别还有大约40个标签,所以也许我会为树木失去森林。

数据包含一组名称和开始/结束时间。目前,如果"杰夫"工作时间为6-9a,他的名字每半小时出现一次(6行数据)。请求是列出" Jeff"从6-9a出现在一条线上。我正在使用" Jeff"在将其应用到表格的其余部分之前作为测试,以便我可以看到可能出现的其他问题;因此,他的名字的测试最终将被删除。

<schedules>
<ES_schedules name="Jeff">
    <tx_starttime>
        <ESP_TIMEDURATION hours="6" minutes="00" seconds="00" durationinseconds="21600"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="6" minutes="30" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Jeff">
    <tx_starttime>
        <ESP_TIMEDURATION hours="6" minutes="30" seconds="00" durationinseconds="23400"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="7" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Jeff">
    <tx_starttime>
        <ESP_TIMEDURATION hours="7" minutes="00" seconds="00" durationinseconds="25200"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="7" minutes="30" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Jeff">
    <tx_starttime>
        <ESP_TIMEDURATION hours="7" minutes="30" seconds="00" durationinseconds="27000"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="8" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Jeff">
    <tx_starttime>
        <ESP_TIMEDURATION hours="8" minutes="00" seconds="00" durationinseconds="28800"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="8" minutes="30" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Jeff">
    <tx_starttime>
        <ESP_TIMEDURATION hours="8" minutes="30" seconds="00" durationinseconds="30600"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="9" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Rich">
    <tx_starttime>
        <ESP_TIMEDURATION hours="9" minutes="00" seconds="00" durationinseconds="32400"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="12" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Jeff">
    <tx_starttime>
        <ESP_TIMEDURATION hours="12" minutes="00" seconds="00" durationinseconds="43200"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="12" minutes="30" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Jeff">
    <tx_starttime>
        <ESP_TIMEDURATION hours="12" minutes="30" seconds="00" durationinseconds="45000"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="13" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Dan">
    <tx_starttime>
        <ESP_TIMEDURATION hours="13" minutes="00" seconds="00" durationinseconds="46800"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="16" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Shane">
    <tx_starttime>
        <ESP_TIMEDURATION hours="16" minutes="00" seconds="00" durationinseconds="57600"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="16" minutes="30" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Sean">
    <tx_starttime>
        <ESP_TIMEDURATION hours="16" minutes="30" seconds="00" durationinseconds="59400"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="17" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Joe">
    <tx_starttime>
        <ESP_TIMEDURATION hours="17" minutes="00" seconds="00" durationinseconds="61200"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="17" minutes="30" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Mark">
    <tx_starttime>
        <ESP_TIMEDURATION hours="17" minutes="30" seconds="00" durationinseconds="63000"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="18" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Kendra">
    <tx_starttime>
        <ESP_TIMEDURATION hours="18" minutes="00" seconds="00" durationinseconds="64800"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="20" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Mark">
    <tx_starttime>
        <ESP_TIMEDURATION hours="20" minutes="00" seconds="00" durationinseconds="72000"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="20" minutes="30" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Crystal">
    <tx_starttime>
        <ESP_TIMEDURATION hours="20" minutes="30" seconds="00" durationinseconds="73800"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="22" minutes="30" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Matthew">
    <tx_starttime>
        <ESP_TIMEDURATION hours="22" minutes="30" seconds="00" durationinseconds="81000"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="23" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Georgia">
    <tx_starttime>
        <ESP_TIMEDURATION hours="23" minutes="00" seconds="00" durationinseconds="82800"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="1" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Ben">
    <tx_starttime>
        <ESP_TIMEDURATION hours="1" minutes="00" seconds="00" durationinseconds="90000"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="3" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="Ben">
    <tx_starttime>
        <ESP_TIMEDURATION hours="3" minutes="00" seconds="00" durationinseconds="97200"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="5" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>
<ES_schedules name="McGregor">
    <tx_starttime>
        <ESP_TIMEDURATION hours="5" minutes="00" seconds="00" durationinseconds="104400"/>
    </tx_starttime>
    <tx_endtime>
        <ESP_TIMEDURATION hours="6" minutes="00" seconds="00"/>
    </tx_endtime>
    <tx_txdate>
        <ESP_DATE year="2016" dateindays="42063"/>
    </tx_txdate>
</ES_schedules>

当我通过Munchean方法运行时,我的输出组&#34; Jeff&#34;不正确。由于他工作6-9a然后12-1p我的输出显示Jeff工作在6a-1p。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:key name="groups" match="schedules/ES_schedules" use="concat(tx_date//@dateindays, '_',@name)"/>

<xsl:template match="/">
    <xsl:for-each select="schedules/ES_schedules[generate-id() = generate-id(key('groups',concat(tx_date//@dateindays, '_',@name))[1])]">
        <xsl:sort select="tx_txdate/ESP_DATE/@dateindays" data-type="number" order="ascending"/>
        <xsl:sort select="tx_starttime/ESP_TIMEDURATION/@durationinseconds" data-type="number" order="ascending"/>
        <xsl:variable name="thisDay" select="tx_txdate/ESP_DATE/@dateindays"/>
        <xsl:variable name="thisGroup" select="@name"/>

        <xsl:value-of select="@name"/>
        <xsl:text> </xsl:text>
        <xsl:choose>
            <xsl:when test="@name = 'Jeff'">
                <xsl:for-each select="/schedules/ES_schedules[tx_txdate/ESP_DATE/@dateindays = $thisDay and @name = 'Jeff']">
                    <xsl:sort data-type="number" select="tx_starttime/ESP_TIMEDURATION/@durationinseconds" order="ascending"/>
                    <xsl:if test="position() = 1">
                        <xsl:apply-templates select="tx_starttime/ESP_TIMEDURATION"/>
                    </xsl:if>
                </xsl:for-each>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="tx_starttime/ESP_TIMEDURATION"/>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:text> - </xsl:text>
        <xsl:choose>
            <xsl:when test="@name = 'Jeff'">
                <xsl:for-each select="/schedules/ES_schedules[tx_txdate/ESP_DATE/@dateindays = $thisDay and @name = $thisGroup]">
                    <xsl:sort data-type="number" select="tx_starttime/ESP_TIMEDURATION/@durationinseconds" order="descending"/>
                    <xsl:if test="position() = 1">
                        <xsl:apply-templates select="tx_endtime/ESP_TIMEDURATION"/>
                    </xsl:if>
                </xsl:for-each>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="tx_endtime/ESP_TIMEDURATION"/>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:text>&#xD;</xsl:text>
    </xsl:for-each>
</xsl:template>

<xsl:template match="ESP_TIMEDURATION">
    <!--2011-09-01T00:00:00.000-->
    <xsl:value-of select="format-number(@hours,'00')"/>
    <xsl:text>:</xsl:text>
    <xsl:value-of select="format-number(@minutes,'00')"/>
    <xsl:text>:</xsl:text>
    <xsl:value-of select="format-number(@seconds,'00')"/>
</xsl:template>

  

Jeff 06:00:00 - 13:00:00 Rich 09:00:00 - 12:00:00 Dan 13:00:00 -   16:00:00 Shane 16:00:00 - 16:30:00 Sean 16:30:00 - 17:00:00 Joe   17:00:00 - 17:30:00 Mark 17:30:00 - 18:00:00 Kendra 18:00:00 -   20:00:00 Crystal 20:30:00 - 22:30:00 Matthew 22:30:00 - 23:00:00   Georgia 23:00:00 - 01:00:00 Ben 01:00:00 - 03:00:00 McGregor 05:00:00    - 06:00:00

我知道我的问题是密钥是基于日期和名称的,但是我不知道如何让XSLT识别出我想要分组,只有前一个时间段具有相同的名称。

2 个答案:

答案 0 :(得分:0)

正如您的评论建议您可以选择使用XSLT 2.0,建议将Muenchian分组替换为for-each-group

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:for-each-group select="/schedules/ES_schedules" group-adjacent="concat(tx_date//@dateindays, '_',@name)">
            <xsl:sort select="tx_txdate/ESP_DATE/@dateindays" data-type="number" order="ascending"/>
            <xsl:sort select="tx_starttime/ESP_TIMEDURATION/@durationinseconds" data-type="number" order="ascending"/>
            <xsl:value-of select="@name"/>
            <xsl:text> </xsl:text>

            <xsl:variable name="sorted" as="element(ES_schedules)*">
                <xsl:perform-sort select="current-group()">
                    <xsl:sort select="xs:decimal(tx_starttime/ESP_TIMEDURATION/@durationinseconds)"></xsl:sort>
                </xsl:perform-sort>
            </xsl:variable>
            <xsl:choose>
                <xsl:when test="@name = 'Jeff'">
                    <xsl:apply-templates select="$sorted[1]/tx_starttime/ESP_TIMEDURATION"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="tx_starttime/ESP_TIMEDURATION"/>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:text> - </xsl:text>
            <xsl:choose>
                <xsl:when test="@name = 'Jeff'">
                    <xsl:apply-templates select="$sorted[last()]/tx_endtime/ESP_TIMEDURATION"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="tx_endtime/ESP_TIMEDURATION"/>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:text>&#xD;</xsl:text>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="ESP_TIMEDURATION">
        <!--2011-09-01T00:00:00.000-->
        <xsl:value-of select="format-number(@hours,'00')"/>
        <xsl:text>:</xsl:text>
        <xsl:value-of select="format-number(@minutes,'00')"/>
        <xsl:text>:</xsl:text>
        <xsl:value-of select="format-number(@seconds,'00')"/>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

据我所知,杰夫的输出应该如下:

Jeff 06:00:00 - 09:00:00
Jeff 12:00:00 - 13:00:00

要继续使用XSLT 1.0,您可以尝试:

<xsl:key name="groups" match="schedules/ES_schedules" 
               use="concat(tx_date//@dateindays, '_',@name)"/>

<xsl:template match="/">
  <xsl:for-each select="schedules/ES_schedules[generate-id() 
             = generate-id(key('groups',concat(tx_date//@dateindays, '_',@name))[1])]">
    <xsl:sort select="tx_txdate/ESP_DATE/@dateindays" 
              data-type="number" 
              order="ascending"/>
    <xsl:sort select="tx_starttime/ESP_TIMEDURATION/@durationinseconds" 
              data-type="number" 
              order="ascending"/>
    <xsl:variable name="thisDay" select="tx_txdate/ESP_DATE/@dateindays"/>
    <xsl:variable name="thisGroup" select="@name"/>

    <xsl:for-each select="key('groups',concat(tx_date//@dateindays, '_',@name))">
                <xsl:sort data-type="number" select="tx_starttime/ESP_TIMEDURATION/@durationinseconds" order="ascending"/>
                <xsl:apply-templates select="."/>
    </xsl:for-each>     
  </xsl:for-each>
</xsl:template>

<xsl:template match="ES_schedules">
  <xsl:variable name="thisStart" select="tx_starttime/ESP_TIMEDURATION" />
  <xsl:variable name="thisEnd" select="tx_endtime/ESP_TIMEDURATION" />

  <xsl:if test="not ( key('groups',concat(tx_date//@dateindays, '_',@name))  
        [ tx_endtime/ESP_TIMEDURATION/@hours = $thisStart/@hours  and  
          tx_endtime/ESP_TIMEDURATION/@minutes = $thisStart/@minutes] )" >
    <xsl:value-of select="@name"/>
    <xsl:text> </xsl:text>
    <xsl:apply-templates select="tx_starttime/ESP_TIMEDURATION"/>
    <xsl:text> - </xsl:text>
  </xsl:if>

  <xsl:if test="not ( key('groups',concat(tx_date//@dateindays, '_',@name))  
        [ tx_starttime/ESP_TIMEDURATION/@hours = $thisEnd/@hours  and  
          tx_starttime/ESP_TIMEDURATION/@minutes = $thisEnd/@minutes] )" >
    <xsl:apply-templates select="tx_endtime/ESP_TIMEDURATION"/>
    <xsl:text>&#xA;</xsl:text>
 </xsl:if>
</xsl:template>

<xsl:template match="ESP_TIMEDURATION">
   <!--2011-09-01T00:00:00.000-->
   <xsl:value-of select="format-number(@hours,'00')"/>
   <xsl:text>:</xsl:text>
   <xsl:value-of select="format-number(@minutes,'00')"/>
   <xsl:text>:</xsl:text>
   <xsl:value-of select="format-number(@seconds,'00')"/>
 </xsl:template>