2016-03-28 2 views
1

Я пытаюсь сгруппировать данные для уменьшения вывода, однако, когда я использую Munchen, я приближаюсь к тому, что хочу, но с ожидаемой «ошибкой» в выходе. Я попытался придумать решение, но у меня кончились идеи!Метод XSLT Munchen и дочерний элемент предыдущего тега XML

Пожалуйста, примите во внимание, что набор данных здесь очень упрощенного просмотра фактических данных, чтобы иметь возможность опубликовать этот вопрос. В реальных данных есть еще около 40 тегов на разных уровнях, поэтому, возможно, я теряю лес для деревьев.

Данные содержат набор названий и время начала и окончания. В настоящее время, если «Jeff» работает с 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 метод ниже моих выходных групп "Jeff" некорректно. Поскольку он работает 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> 

Джефф 6:00:00 - 13:00:00 Rich 9:00:00 - 12:00:00 Dan 13:00:00 - 16:00:00 Шейн 16:00:00 - 16:30:00 Шон 16:30:00 - 17:00:00 Джо 17:00:00 - 17:30:00 Март 17:30:00 - 18:00:00 Кендра 18:00:00 - 20:00:00 Кристалл 20:30:00 - 22:30:00 Мэтью 22:30:00 - 23:00:00 Грузия 23:00:00 - 01:00:00 Бен 01:00:00 - 03:00:00 McGregor 05:00:00 - 06:00:00

Я знаю, что моя проблема в том, что ключ основан на дате и имени, но я не уверен, как заставить XSLT распознавать, что я хочу сгруппировать, только если предыдущий период времени имеет то же имя.

+1

кажется, л ike хорошая работа для XSLT 2.0, выполняющая ' ... '. –

+0

Возможно, я использую это неправильно, так как большая часть нашей работы находится в XSLT 1.0, но когда я использую для каждой группы, я получаю «Jeff 06:00:00 - 13:00:00», появляющийся как для 6a, так и для 12p раз. Поэтому, пока имя отображается правильно, время начала/окончания не изменяется. Это делает его таким, что что-то, что известно группе, должно присутствовать в начальных и конечных временных зонах. –

+0

Я думаю, у вас все еще есть '' который, конечно же, должен быть заменен на '< xsl: for-each select = "current-group()"> '(или, возможно, некоторое вычисление min/max). –

ответ

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> 
+0

Возможно, я что-то пропустил. Но если я прав, это будет работать только потому, что есть богатая запись между записями Джеффа? –

+0

@ hr_117, вы правы, я в основном пытался обеспечить решение проблемы «Я не уверен, как заставить XSLT распознавать, что я хочу группировать, только если предыдущий период времени имеет то же имя». Является ли это решением реальной проблемы, я не уверен теперь, что я видел вашу интерпретацию и предложил решение проблемы. Посмотрим, что должен сказать Джейсон. –

0

Как я понял выход для Jeff должен быть следующий:

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> 
Смежные вопросы