Search code examples
xmlxslttransformxslt-1.0xslt-grouping

XSLT to find lowest price


i am beginner in XSLT and using to transform XML to XML.

I require to get Prices tag which has lowest sum.

Source XML:

<Result>
    <Fares>
        <Fare>
            <Prices>
                <Price type="adt" ticket="15"/>
                <Price type="chd" ticket="10"/>
                <Price type="inf" ticket="10"/>
            <Prices>
        </Fare>
        <Fare>
            <Prices>
                <Price type="adt" ticket="10"/>
                <Price type="chd" ticket="10"/>
                <Price type="inf" ticket="10"/>
            <Prices>
        </Fare>
        <Fare>
            <Prices>
                <Price type="adt" ticket="5"/>
                <Price type="chd" ticket="5"/>
                <Price type="inf" ticket="5"/>
            <Prices>
        </Fare>
        <Fare>
            <Prices>
                <Price type="adt" ticket="10"/>
                <Price type="chd" ticket="5"/>
                <Price type="inf" ticket="5"/>
            <Prices>
        </Fare>
    </Fares>
</Result>

XSLT:

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

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

    <xsl:template match="Result">
        <xsl:element name="Lowest">
            <xsl:variable name="lowest" select="Fares/Fare/Prices[not(sum(Price/@ticket) &gt; //Fares/Fare/Prices[sum(Price/@ticket)])]"/>
            <xsl:copy-of select="$lowest"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Output:

<Lowest>
    <Prices>
        <Price type="adt" ticket="15"/>
        <Price type="chd" ticket="10"/>
        <Price type="inf" ticket="10"/>
    <Prices/>
    </Prices>
</Lowest>

Expected Output:

<Lowest>
    <Prices Total="15">
        <Price type="adt" ticket="5"/>
        <Price type="chd" ticket="5"/>
        <Price type="inf" ticket="5"/>
    <Prices>
</Lowest>

As shown above output should have the Prices tag with lowest value as attribute also.

Please help.


Solution

  • This transformation:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="/">
         <xsl:for-each select="/*/*/Fare">
           <xsl:sort select="sum(Prices/Price/@ticket)" data-type="number"/>
    
           <xsl:if test="position()=1">
             <Lowest Total="{sum(Prices/Price/@ticket)}">
               <xsl:copy-of select="Prices"/>
             </Lowest>
           </xsl:if>
         </xsl:for-each>
     </xsl:template>
    </xsl:stylesheet>
    

    when applied on the provided XML document (with several malformities corrected!!!):

    <Result>
        <Fares>
            <Fare>
                <Prices>
                    <Price type="adt" ticket="15"/>
                    <Price type="chd" ticket="10"/>
                    <Price type="inf" ticket="10"/>
                </Prices>
            </Fare>
            <Fare>
                <Prices>
                    <Price type="adt" ticket="10"/>
                    <Price type="chd" ticket="10"/>
                    <Price type="inf" ticket="10"/>
                </Prices>
            </Fare>
            <Fare>
                <Prices>
                    <Price type="adt" ticket="5"/>
                    <Price type="chd" ticket="5"/>
                    <Price type="inf" ticket="5"/>
                </Prices>
            </Fare>
            <Fare>
                <Prices>
                    <Price type="adt" ticket="10"/>
                    <Price type="chd" ticket="5"/>
                    <Price type="inf" ticket="5"/>
                </Prices>
            </Fare>
        </Fares>
    </Result>
    

    produces the wanted, correct result:

    <Lowest Total="15">
       <Prices>
          <Price type="adt" ticket="5"/>
          <Price type="chd" ticket="5"/>
          <Price type="inf" ticket="5"/>
       </Prices>
    </Lowest>