2014-01-21 6 views
0

Я пытаюсь отобразить Hoursofoperation для разных отделов, у меня есть шаблон, который работает для одного элемента HoursofOperation для нескольких элементов HoursofOperation, он не дает ожидаемого результата. код нижеПроблема с xsl-ключом для нескольких элементов

<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:00 pmSat10:00am - 6:00 pmSun11:00am - 6:00 вечера

шаблон работает отлично для продаж HoursOfOperation элемента, но и для обслуживания он не работает, как expected.i не понял, что это оператор выбора делает именно <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 

ответ

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

- это экземпляр метода «Muenchian grouping», способ группировки элементов на основе некоторого значения, которое они имеют вместе. В этом конкретном выражении будут выделены все дочерние элементы текущего элемента контекста DaysOfWeek, которые являются первым упоминанием их конкретной комбинации времени начала и окончания всего документа.

Если вы хотите использовать группировку Muenchian, но ограничиваете ее группировкой в ​​определенном разделе документа, вам необходимо включить что-то, что однозначно идентифицирует этот раздел как часть значения ключа (так что первый элемент с временем начала 1 и время окончания 2 в секции A имеет другое значение ключа от первого элемента с тем же начальным и конечным временем, но в пределах раздела 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. -->