XSLT 1.0 Найти уникальный узел с максимальным значением

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

Исходный XML:

<Response>
    <Flight>
        <From>A</From>
        <To>B</To>
        <Passengers>
            <Passenger>
                <Fare>200</Fare>
                <Fee>15</Fee>
                <Type>ADT</Type>
            </Passenger>
            <Passenger>
                <Fare>200</Fare>
                <Fee>15</Fee>
                <Type>ADT</Type>
            </Passenger>
            <Passenger>
                <Fare>150</Fare>
                <Fee>15</Fee>
                <Type>CHD</Type>
            </Passenger>
        </Passengers>
    </Flight>
    <Flight>
        <From>B</From>
        <To>A</To>
        <Passengers>
            <Passenger>
                <Fare>250</Fare>
                <Fee>25</Fee>
                <Type>ADT</Type>
            </Passenger>
            <Passenger>
                <Fare>250</Fare>
                <Fee>25</Fee>
                <Type>ADT</Type>
            </Passenger>
            <Passenger>
                <Fare>100</Fare>
                <Fee>25</Fee>
                <Type>CHD</Type>
            </Passenger>
        </Passengers>
    </Flight>
</Response>

Как показано в приведенном выше XML-коде, существует результат поездки туда и обратно для пункта отправления A-B, и я собираюсь купить билеты на оба рейса. Мне нужно рассчитать общую стоимость проезда, сбор (в зависимости от того, что выше для обоих рейсов) и его общую стоимость.

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

<Result>
    <PassengerGroup TotalFare="1150" TotalFee="75" TotalPrice="1225"/>
</Result>

Здесь,

  • TotalFare — это сумма всех тегов Fare.
  • TotalFee - это большее значение каждого типа пассажиров, умноженное на количество пассажиров этого типа.
  • например Для ADT большее значение комиссии составляет 25, а количество ADT равно 2, поэтому общая комиссия за ADT составляет 50. Для CHD большее значение комиссии составляет 25, а количество CHD равно 1, поэтому общая комиссия для CHD составляет 25. Таким образом, окончательная общая сумма комиссии = 75.
  • TotalPrice является суммой атрибутов ToatalFare и TotalFee.

Я пробовал с XSLT ниже.

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
version="1.0" xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exslt">

    <xsl:output method="xml" indent="yes" />

    <xsl:template match="Response">
        <xsl:element name="Result">
            <xsl:element name="PassengerGroup">
                <xsl:attribute name="TotalFare">
                    <xsl:value-of select="sum(//Flight/Passengers/Passenger/Fare)"/>
                </xsl:attribute>
                <xsl:attribute name="TotalFee">
                    <xsl:value-of select="sum(//Flight/Passengers/Passenger[not(Type=preceding::Passenger/Type)]/Fee)"/>
                </xsl:attribute>
                <xsl:attribute name="TotalFee">
                    <xsl:value-of select="sum(//Flight/Passengers/Passenger/Fare) + sum(//Flight/Passengers/Passenger/Fee)"/>
                </xsl:attribute>
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

и получил вывод ниже.

Вывод:

<Result>
  <PassengerGroup TotalFare="1150" TotalFee="30" TotalPrice="1270"/>
</Result>

TotalFee вычисляется неправильно. Пожалуйста помоги. Спасибо.


person Ankur Raiyani    schedule 22.02.2013    source источник
comment
Вы говорите, что количество пассажиров АДТ 2, а на самом деле 4...??? Пожалуйста, отредактируйте вопрос и исправьте.   -  person Dimitre Novatchev    schedule 23.02.2013
comment
@DimitreNovatchev - Количество пассажиров ADT равно 2. Исходный XML содержит разные цены ADT на разных рейсах. Первый тег Flight показывает, что если вы путешествуете этим рейсом, он будет стоить 200+15=215, второй Flight показывает, что если вы путешествуете этим рейсом, он будет взимать плату 250+25=275.   -  person Ankur Raiyani    schedule 25.02.2013


Ответы (1)


Я считаю, что это должно сделать это:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exslt">
  <xsl:output method="xml" indent="yes" />
  <xsl:key name="kPassenger" match="Passenger" use="Type" />

  <!-- The passenger nodes from just the first flight, so we can count how many of 
       each type there are -->
  <xsl:variable name="passengers" select="Response/Flight[1]/Passengers/Passenger" />

  <xsl:template match="Response">
    <xsl:variable name="totalFare" select="sum(Flight/Passengers/Passenger/Fare)" />
    <xsl:variable name="feeByPassenger">
      <xsl:apply-templates 
         select="$passengers[generate-id() = 
                             generate-id(key('kPassenger', Type)[1])]"
         mode="fee" />
    </xsl:variable>
    <xsl:variable name="totalFee" 
                  select="sum(exslt:node-set($feeByPassenger)/*/@value)" />

    <Result>
      <PassengerGroup TotalFare="{$totalFare}" TotalFee="{$totalFee}" 
                      TotalPrice="{$totalFare + $totalFee}" />
    </Result>
  </xsl:template>

  <xsl:template match="Passenger" mode="fee">
    <xsl:variable name="maxFee">
      <xsl:apply-templates select="key('kPassenger', Type)/Fee">
        <xsl:sort select="." data-type="number" order="descending"/>
      </xsl:apply-templates>
    </xsl:variable>
    <fee value="{$maxFee * count($passengers[Type = current()/Type])}"/>
  </xsl:template>

  <xsl:template match="Fee">
    <xsl:if test="position() = 1">
      <xsl:value-of select="." />
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

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

<Result>
  <PassengerGroup TotalFare="1150" TotalFee="75" TotalPrice="1225" />
</Result>
person JLRishe    schedule 11.03.2013