2016-07-05 12 views
0

У меня есть следующие данные, где у меня есть несколько атрибутов: Мне нужно сортировать по дате или по часовой пояс в порядке возрастания. Если ввод содержит разные даты и время, то он должен выходить по возрастанию в течение Datetime. Если вход содержит те же даты и время, что и часовой пояс, он должен выводить по возрастанию в часовую зону.xsl: Сортировать несколько атрибутов

Текущая логика:

<xsl:sort select="@Datetime" order="ascending"/> 
    <xsl:sort select="@Timezone" order="ascending"/> 

ОБРАЗЦА первый сценарий - выход, как и ожидалось:

<MSG> 
<DOC> 
<Parent> 
<Input Id="1234567890" Srvce="RRR" Cd="D1" Datetime="2016-06-16 20:42:30" Timezone="+02:00" EvtRmk="DUMMY 1"> 
</Input> 
<Input Id="1234567890" Srvce="RRR" Cd="D1" Datetime="2016-06-15 20:43:15" Timezone="+04:00" EvtRmk="DUMMY 1"> 
</Input> 

Токовый выход:

<Output>2016-06-15 20:43:15"</Output> 
    <Output>2016-06-16 20:42:30</Output> 

ОБРАЗЦА второй сценарий - Различные Timezone/Same Datetime; выход не отсортирован в Timezone:

<MSG> 
</DOC> 
<Parent> 
<Input Id="1234567890" Srvce="RRR" Cd="D1" Datetime="2016-06-15 20:42:30" Timezone="+04:00" EvtRmk="DUMMY 1"> 
</Input> 
<Input Id="1234567890" Srvce="RRR" Cd="D1" Datetime="2016-06-15 20:43:15" Timezone="+00:00" EvtRmk="DUMMY 1"> 
</Input> 

Выходной ток:

<Output>2016-06-15 20:42:30</Output> 
<Output>2016-06-15 20:43:15</Output> 

Ожидаемый результат:

<Output>2016-06-15 20:43:15</Output> 
<Output>2016-06-15 20:42:30</Output> 
+0

Ты говоришь, что хочешь, результат сортировки в абсолютном хронологическом порядке заказ? Это эквивалентно преобразованию всего в UTC сначала и сортировке по метке времени. –

+0

Да, вы правы, его нужно сортировать в хронологическом порядке. –

+0

Ваше ожидание необоснованно: если вы сначала сортируете по дате времени, тогда '2016-06-15 20: 42: 30' всегда будет перед' 2016-06-15 20: 43: 15'. Любая вторичная сортировка будет применяться только в группах, созданных первой сортировкой. –

ответ

0

В XSLT 1.0, вам придется сделать это в два прохода: первый , сравните дату ввода данных с общей базой, такой как UTC, а затем отсортируйте результаты по этому значению:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

<xsl:template match="Parent"> 
    <!-- first-pass --> 
    <xsl:variable name="inputs"> 
     <xsl:for-each select="Input"> 
      <input> 
       <xsl:copy-of select="@*"/> 
       <xsl:call-template name="dateTime-to-seconds"> 
        <xsl:with-param name="dateTime" select="@Datetime" /> 
        <xsl:with-param name="offset" select="@Timezone" /> 
       </xsl:call-template> 
      </input>  
     </xsl:for-each> 
    </xsl:variable> 
    <!-- output --> 
    <xsl:copy> 
     <xsl:for-each select="exsl:node-set($inputs)/input"> 
      <xsl:sort select="." data-type="number" order="ascending"/> 
      <Input> 
       <xsl:copy-of select="@*"/> 
      </Input> 
     </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

<xsl:template name="dateTime-to-seconds"> 
    <xsl:param name="dateTime"/> 
    <xsl:param name="offset"/> 

    <xsl:variable name="date" select="substring-before($dateTime, ' ')" /> 
    <xsl:variable name="local-time" select="substring-after($dateTime, ' ')" /> 

    <xsl:variable name="year" select="substring($date, 1, 4)" /> 
    <xsl:variable name="month" select="substring($date, 6, 2)" /> 
    <xsl:variable name="day" select="substring($date, 9, 2)" /> 

    <xsl:variable name="hour" select="substring($local-time, 1, 2)" /> 
    <xsl:variable name="minute" select="substring($local-time, 4, 2)" /> 
    <xsl:variable name="second" select="substring($local-time, 7)" /> 

    <xsl:variable name="offset-sign" select="1 - 2 * starts-with($offset, '-')" /> 
    <xsl:variable name="offset-hour" select="substring($offset, 2, 2) * $offset-sign" /> 
    <xsl:variable name="offset-minute" select="substring($offset, 5, 2) * $offset-sign" /> 

    <xsl:variable name="a" select="floor((14 - $month) div 12)"/> 
    <xsl:variable name="y" select="$year + 4800 - $a"/> 
    <xsl:variable name="m" select="$month + 12*$a - 3"/>  
    <xsl:variable name="jd" select="$day + floor((153*$m + 2) div 5) + 365*$y + floor($y div 4) - floor($y div 100) + floor($y div 400) - 32045" /> 

    <xsl:value-of select="86400*$jd + 3600*$hour + 60*$minute + $second - 3600*$offset-hour - 60*$offset-minute" /> 
</xsl:template> 

</xsl:stylesheet> 

Применительно к следующему входу теста:

XML

<Parent> 
    <Input Id="001" Datetime="2016-06-15 19:44:30" Timezone="-02:30"/> 
    <Input Id="002" Datetime="2016-06-15 20:42:30" Timezone="+04:00"/> 
    <Input Id="003" Datetime="2016-06-15 21:43:15" Timezone="+00:00"/> 
</Parent> 

результат будет:

<?xml version="1.0" encoding="UTF-8"?> 
<Parent> 
    <Input Id="002" Datetime="2016-06-15 20:42:30" Timezone="+04:00"/> 
    <Input Id="003" Datetime="2016-06-15 21:43:15" Timezone="+00:00"/> 
    <Input Id="001" Datetime="2016-06-15 19:44:30" Timezone="-02:30"/> 
</Parent> 
Смежные вопросы