多个元素的xsl-key问题

时间:2014-01-21 18:33:58

标签: xslkey

我正在尝试显示不同部门的营业时间,我有一个模板,用于多个HoursofOperation元素的单个HoursofOperation元素,它没有给出预期的结果。代码在下面

<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="similarDays" 
             match="DaysOfWeek" 
             use="concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure)" />

    <xsl:template match="/">

        <xsl:for-each select="dealers/HoursOfOperation">
            <xsl:if test="HoursTypeCode ='Service'">
                From service:
                    <xsl:for-each select="DaysOfWeek[count(. | key('similarDays', concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))[1]) = 1]">

                        <xsl:for-each select="key('similarDays', concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))">
                            <dt>
                                <xsl:value-of select="substring(DayOfWeekCode,1,3)"/>
                                <xsl:if test="position()!=last()">
                                    <xsl:text>, </xsl:text>
                                </xsl:if>
                            </dt>
                        </xsl:for-each>                                                 
                        <dd>
                            <xsl:call-template name="minutes2time">
                                <xsl:with-param name="minutes" select="AvailabilityStartTimeMeasure"/>
                            </xsl:call-template>
                            <xsl:text> - </xsl:text>
                            <xsl:call-template name="minutes2time">
                                <xsl:with-param name="minutes" select="AvailabilityEndTimeMeasure"/>
                            </xsl:call-template>
                        </dd>                   
                    </xsl:for-each>
            </xsl:if>
            <xsl:if test="HoursTypeCode ='Sales'">
                From Sales:
                <xsl:for-each select="DaysOfWeek[count(. | key('similarDays', concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))[1]) = 1]">

                        <xsl:for-each select="key('similarDays', concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))">
                            <dt>
                                <xsl:value-of select="substring(DayOfWeekCode,1,3)"/>
                                <xsl:if test="position()!=last()">
                                    <xsl:text>, </xsl:text>
                                </xsl:if>
                            </dt>
                        </xsl:for-each>                                                 
                        <dd>
                            <xsl:call-template name="minutes2time">
                                <xsl:with-param name="minutes" select="AvailabilityStartTimeMeasure"/>
                            </xsl:call-template>
                            <xsl:text>am - </xsl:text>
                            <xsl:call-template name="minutes2time">
                                <xsl:with-param name="minutes" select="AvailabilityEndTimeMeasure"/>
                            </xsl:call-template>
                            <xsl:text>pm</xsl:text>
                        </dd>

                </xsl:for-each>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="minutes2time">
        <xsl:param name="minutes"/>
        <xsl:variable name="h" select="floor($minutes div 60)"/>    
        <xsl:variable name="m" select="$minutes mod 60"/>
        <xsl:variable name="pad" select="substring('0', 1, $m &lt; 10)"/>
        <xsl:choose>
            <xsl:when test="$h &gt; 12">
                <xsl:value-of select="concat(($h)-12, ':', $pad, $m)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="concat($h, ':', $pad, $m)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>    
</xsl:stylesheet>

XML: -

<dealers>
    <HoursOfOperation>
        <HoursTypeCode>Service</HoursTypeCode>
        <DaysOfWeek>
            <DayOfWeekCode>Monday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">420</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Tuesday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">420</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Wednesday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">420</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Thursday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">420</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Friday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">420</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Saturday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">420</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Sunday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">420</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
    </HoursOfOperation>
    <HoursOfOperation>
        <HoursTypeCode>Parts</HoursTypeCode>
        <DaysOfWeek>
            <DayOfWeekCode>Monday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">480</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1050</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Tuesday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">480</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1050</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Wednesday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">480</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1050</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Thursday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">480</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1050</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Friday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">480</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1050</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Saturday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">480</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">990</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Sunday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">420</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
    </HoursOfOperation>
    <HoursOfOperation>
        <HoursTypeCode>Sales</HoursTypeCode>
        <DaysOfWeek>
            <DayOfWeekCode>Monday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">510</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1140</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Tuesday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">510</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1140</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Wednesday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">510</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1140</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Thursday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">510</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1140</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Friday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">510</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1140</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Saturday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">600</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
        <DaysOfWeek>
            <DayOfWeekCode>Sunday</DayOfWeekCode>
            <AvailabilityStartTimeMeasure unitCode="minute">660</AvailabilityStartTimeMeasure>
            <AvailabilityEndTimeMeasure unitCode="minute">1080</AvailabilityEndTimeMeasure>
        </DaysOfWeek>
    </HoursOfOperation>
</dealers>

输出: -

  

服务时间:周一,周二,周三,周四,周五,周六,周日,周日7:00-6:00   销售:周一,周二,周三,周四,周五:上午30点 - 下午7点,上午10点 -   下午6:00,上午11:00 - 下午6:00

模板适用于Sales HoursOfOperation元素,但是对于服务它没有按预期工作。我不明白这个select语句正在做什么<xsl:for-each select="DaysOfWeek[count(. | key('similarDays', concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))[1]) = 1]">

期望的输出: -

From service:Mon - Sun 7:00am - 6:00pm
From Sales:Mon - Fri 8:30am - 7:00pm
Sat 10:00am - 6:00pm
Sun 11:00am - 6:00pm

1 个答案:

答案 0 :(得分:0)

DaysOfWeek[count(. | key('similarDays', concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))[1]) = 1]

是“Muenchian分组”方法的一个实例,这是一种基于它们共有的一些值将元素组合在一起的方法。此特定表达式将选择当前上下文元素的所有DaysOfWeek子元素,这些元素是在整个文档中首次提及其开始和结束时间的特定组合。

如果您想使用Muenchian分组但是将其限制为在文档的特定部分内进行分组,那么您需要包含一些唯一标识该部分作为键值的一部分的内容(以便第一个元素具有开始时间1和A部分中的结束时间2与第一个元素具有不同的键值,具有相同的开始和结束时间但在B)部分内。对于您的情况,合适的唯一标识符可能是HoursTypeCode

<xsl:key name="similarDays" 
         match="DaysOfWeek" 
         use="concat(../HoursTypeCode, '|',
                     AvailabilityStartTimeMeasure, '|',
                     AvailabilityEndTimeMeasure)" />

分组表达式需要包含相同的唯一标识符

<xsl:if test="HoursTypeCode ='Service'">
  From service:
  <xsl:for-each select="DaysOfWeek[count(. |
      key('similarDays', concat('Service|', AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))[1]) = 1]">

     <xsl:for-each select="key('similarDays', concat('Service|', AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))">

当然,不是<xsl:if>块复制“来自销售”和“来自服务”的整套逻辑,你可以在同一个块中处理它们,从HoursTypeCode获取部分名称:

    <xsl:for-each select="dealers/HoursOfOperation">
      From <xsl:value-of select="HoursTypeCode"/>:
      <xsl:for-each select="DaysOfWeek[count(. |
          key('similarDays', concat(current()/HoursTypeCode, '|', AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))[1]) = 1]">
        <!-- etc. -->