XSLT: фильтровать и применять условную логику при группировании / сортировке - PullRequest
0 голосов
/ 10 ноября 2011

Для входного XML, например:

<FlightOptions>
  <item>
     <Fares>
       <item>
         <FareClass>A</FareClass>
         <Fare>100</Fare>
         <FareType>E</FareType>
         <Seats>5</Seats>
       </item>
       <item>
         <FareClass>B</FareClass>
         <Fare>200</Fare>
         <FareType>E</FareType>
         <Seats>10</Seats>
       </item>
       <item>
         <FareClass>C</FareClass>
         <Fare>250</Fare>
         <FareType>E</FareType>
         <Seats>20</Seats>
       </item>
       <item>
         <FareClass>N</FareClass>
         <Fare>100</Fare>
         <FareType>F</FareType>
         <Seats>5</Seats>
       </item>
       <item>
         <FareClass>M</FareClass>
         <Fare>200</Fare>
         <FareType>F</FareType>
         <Seats>50</Seats>
       </item>
       <item>
         <FareClass>O</FareClass>
         <Fare>300</Fare>
         <FareType>F</FareType>
         <Seats>20</Seats>
       </item>
     </Fares>
     <Flight>
         <FlightNumber>YY232</FlightNumber>
         <Origin>JFK</Origin>
         <Destination>LHR</Destination>
         <DepTime>1300</DepTime>
         <ArrTime>2000</ArrTime>
     </Flight>
    </item>
</FlightOptions>

Для вышеупомянутого XML мне нужно сохранить только несколько узлов Fares / item, где я сначала группирую по FareType (E и F), и сохраняю элементы, начиная ссамый дешевый тариф, но остановка, если количество мест>> 9. Например, поскольку у А всего 5 мест, мне нужно выбрать следующий самый высокий тариф Б, но не С. Кроме того, если количество мест> = 9, мне нужно ограничитьэто до 9.

Я могу сделать группу и отсортировать, но не могу пройти тарифы и применить логику, чтобы выбрать тарифы, пока число мест <= 9 для этого FareType.Другая сложность заключается в том, что выходной XML должен переупорядочить значения Fares / items таким образом, чтобы узлы FareType E находились вначале в порядке убывания Fare, за которым следовал узел N (если он присутствует в источнике), а затем другие узлы FareType F в порядке убыванияТариф. </p>

Выходной XML будет выглядеть так:

<FlightOptions>
  <item>
     <Fares>
       <item>
         <FareClass>B</FareClass>
         <Fare>200</Fare>
         <FareType>E</FareType>
         <Seats>9</Seats>
       </item>
       <item>
         <FareClass>A</FareClass>
         <Fare>100</Fare>
         <FareType>E</FareType>
         <Seats>5</Seats>
       </item>
       <item>
         <FareClass>N</FareClass>
         <Fare>100</Fare>
         <FareType>F</FareType>
         <Seats>5</Seats>
       </item>
       <item>
         <FareClass>M</FareClass>
         <Fare>200</Fare>
         <FareType>F</FareType>
         <Seats>9</Seats>
       </item>
     </Fares>
     <Flight>
         <FlightNumber>YY232</FlightNumber>
         <Origin>JFK</Origin>
         <Destination>LHR</Destination>
         <DepTime>1300</Deptime>
         <ArrTime>2000</ArrTime>
     </Flight>
    </item>
<FlightOptions>

Я пытался прочитать примеры мюнхенской группировки, но у меня возникли проблемы с пониманием того, как подать заявку вместе с преобразованием идентичности (так как мне нужносохранить структуру Полёта вместе с узлами Тарифы / предметы).

Спасибо!

1 Ответ

0 голосов
/ 11 ноября 2011

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

Таким образом, при сопоставлении элемента Fares вы сортируете элементы item , например

     <xsl:apply-templates select="item">
        <xsl:sort select="FareType"/>
        <xsl:sort select="Fare"/>
     </xsl:apply-templates>

Далее, когда вы сопоставляете каждый такой элемент item , вы можете просто проверить, больше ли какой-либо предыдущий элемент с тем же FareType равен 9. Если таких узлов нет , то, поскольку вы отсортировали по Fare, вы знаете, что включили узел.

<xsl:template match="Fares/item">
    <xsl:if test="not(preceding-sibling::item[FareType=current()/FareType][Seats > 9])">
       <!-- copy node -->
    </xsl:if>

Вот полный XSLT ...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:template match="Fares">
      <xsl:copy>
         <xsl:apply-templates select="item">
            <xsl:sort select="FareType"/>
            <xsl:sort select="Fare"/>
         </xsl:apply-templates>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="Fares/item">
      <xsl:if test="not(preceding-sibling::item[FareType=current()/FareType][Seats > 9])">
         <xsl:call-template name="identity"/>
      </xsl:if>
   </xsl:template>

   <xsl:template match="Seats[. > 9]">
      <xsl:copy>9</xsl:copy>
   </xsl:template>

   <xsl:template match="@*|node()">
      <xsl:call-template name="identity"/>
   </xsl:template>

   <xsl:template name="identity">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

При применении к вашему образцу XML выводится следующее:

<FlightOptions>
   <item>
      <Fares>
         <item>
            <FareClass>A</FareClass>
            <Fare>100</Fare>
            <FareType>E</FareType>
            <Seats>5</Seats>
         </item>
         <item>
            <FareClass>B</FareClass>
            <Fare>200</Fare>
            <FareType>E</FareType>
            <Seats>9</Seats>
         </item>
         <item>
            <FareClass>N</FareClass>
            <Fare>100</Fare>
            <FareType>F</FareType>
            <Seats>5</Seats>
         </item>
         <item>
            <FareClass>M</FareClass>
            <Fare>200</Fare>
            <FareType>F</FareType>
            <Seats>9</Seats>
         </item>
      </Fares>
      <Flight>
         <FlightNumber>YY232</FlightNumber>
         <Origin>JFK</Origin>
         <Destination>LHR</Destination>
         <DepTime>1300</DepTime>
         <ArrTime>2000</ArrTime>
      </Flight>
   </item>
</FlightOptions>

Также обратите внимание на совпадение шаблона для Мест , чтобы ограничить его до 9.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...