【问题标题】:issue with xsl-key for multiple elements多个元素的 xsl-key 问题
【发布时间】:2014-01-21 18:33:58
【问题描述】:

我正在尝试显示不同部门的 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 起 销售:周一,周二,周三,周四,周五8:30am - 7:00pmSat10:00am - 下午 6:00 上午 11:00 - 下午 6:00

模板对于 Sales HoursOfOperation 元素运行良好,但对于服务却没有按预期运行。我不明白这个 select 语句到底在做什么 &lt;xsl:for-each select="DaysOfWeek[count(. | key('similarDays', concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))[1]) = 1]"&gt;

期望的输出:-

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

【问题讨论】:

    标签: xslkey


    【解决方案1】:
    DaysOfWeek[count(. | key('similarDays', concat(AvailabilityStartTimeMeasure, '|', AvailabilityEndTimeMeasure))[1]) = 1]
    

    是“M​​uenchian 分组”方法的一个实例,一种基于元素具有的某些共同值将元素组合在一起的方法。这个特定的表达式将选择当前上下文元素的所有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))">
    

    当然,除了 &lt;xsl:if&gt; 块复制“来自销售”和“来自服务”的整个逻辑集之外,您还可以在同一块中处理它们,并从 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. -->
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-03
      • 1970-01-01
      • 2016-01-11
      • 2016-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多