0

So, I have this XML file (below) and I'm trying to make a list of Reservations per Customer. Since customers are "inside" Reservations and are not unique (multiple customers can perform different reservations), I've been facing a problem: I can retrieve the right amount of Reservations per Customer but they appear the number of times that customer exists in the file, because I go throw all Reservations every time...

Can you, please, help me with this? I need to not send to the HTML file, Customers that have been already processed.


My XML file:

<?xml version="1.0" encoding="UTF-8" ?>
<System xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file:///C:/Users/ASUS/Documents/lprog-xml/Reservations.xsd">
    <Reservations>
        <Reservation id="b1">
            <CourierToken>abb456fb</CourierToken>
            <CustomerToken>fsdg432n</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>12</day>
                    <month>12</month>
                    <year>2016</year>
                </Calendar>
            </BeginDate>
            <Term>20</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>pms</Username>
                <Password>sdasda</Password>
                <FirstName>Pedro</FirstName>
                <LastName>Pinto</LastName>
                <Email>xmllover4everAndEver64cm@email.com</Email>
            </Customer>
        </Reservation>
        <Reservation id="a2">
            <CourierToken>dfsd43b2</CourierToken>
            <CustomerToken>f3hu32mu</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>13</day>
                    <month>January</month>
                    <year>2017</year>
                </Calendar>
            </BeginDate>
            <Term>5</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>xss</Username>
                <Password>asdq</Password>
                <FirstName>Xavier</FirstName>
                <LastName>Silva</LastName>
                <Email>theincredibleone@email.com</Email>
            </Customer>
        </Reservation>
        <Reservation id="a342">
            <CourierToken>d4fd43b2</CourierToken>
            <CustomerToken>f3htg2mu</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>10</day>
                    <month>March</month>
                    <year>2016</year>
                </Calendar>
            </BeginDate>
            <Term>45</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>xss</Username>
                <Password>asdq</Password>
                <FirstName>Xavier</FirstName>
                <LastName>Silva</LastName>
                <Email>theincredibleone@email.com</Email>
            </Customer>
        </Reservation>
        <Reservation id="b3">
            <CourierToken>desfg236</CourierToken>
            <CustomerToken>43jmfh23</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>1</day>
                    <month>January</month>
                    <year>2017</year>
                </Calendar>
            </BeginDate>
            <Term>8</Term>
            <DropPoint id="g34"/>
            <Customer>
                <Username>dal</Username>
                <Password>dasdg</Password>
                <FirstName>Daniel</FirstName>
                <LastName>Almeida</LastName>
                <Email>dokkanBattleFTW@email.com</Email>
            </Customer>
        </Reservation>
        <Reservation id="a56">
            <CourierToken>5bh4fdsf</CourierToken>
            <CustomerToken>onfdsn43</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>23</day>
                    <month>9</month>
                    <year>2018</year>
                </Calendar>
            </BeginDate>
            <Term>15</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>pops</Username>
                <Password>iHack</Password>
                <FirstName>Migas</FirstName>
                <LastName>what</LastName>
                <Email>getHackedM8@rekt.com</Email>
            </Customer>
        </Reservation>
        <Reservation id="t345">
            <CourierToken>432njdas</CourierToken>
            <CustomerToken>efg234jn</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>25</day>
                    <month>11</month>
                    <year>2567</year>
                </Calendar>
            </BeginDate>
            <Term>56</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>SenorJobs</Username>
                <Password>gr8b8m8ir88/8</Password>
                <FirstName>Steve</FirstName>
                <LastName>Jobs</LastName>
                <Email>iOwnAppleBitches@email.com</Email>
            </Customer>
        </Reservation>
        <Reservation id="p45">
            <CourierToken>acw4tsca</CourierToken>
            <CustomerToken>ascfdv32</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>19</day>
                    <month>5</month>
                    <year>2020</year>
                </Calendar>
            </BeginDate>
            <Term>7</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>SenorGates</Username>
                <Password>VivaLaMicrosoft</Password>
                <FirstName>Billy</FirstName>
                <LastName>Gator</LastName>
                <Email>cyaSteve@email.com.apple.pt</Email>
            </Customer>
        </Reservation>
        <Reservation id="df45">
            <CourierToken>34rfdf3d</CourierToken>
            <CustomerToken>554fgdvv</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>21</day>
                    <month>10</month>
                    <year>2020</year>
                </Calendar>
            </BeginDate>
            <Term>20</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>CristianoPenaldo</Username>
                <Password>saudadesIrina</Password>
                <FirstName>Cristiano</FirstName>
                <LastName>Ronaldo</LastName>
                <Email>esteMessiJaMeteNojo@email.com</Email>
            </Customer>
        </Reservation>
        <Reservation id="po454">
            <CourierToken>dfsg345d</CourierToken>
            <CustomerToken>sadfg345</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>31</day>
                    <month>2</month>
                    <year>2345</year>
                </Calendar>
            </BeginDate>
            <Term>23</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>ZLATAN</Username>
                <Password>iAmZlatan</Password>
                <FirstName>Zlatan</FirstName>
                <LastName>Ibrahimovic</LastName>
                <Email>rektByZlatan@email.com</Email>
            </Customer>
        </Reservation>
        <Reservation id="sd34">
            <CourierToken>34567asd</CourierToken>
            <CustomerToken>dssfdgh4</CustomerToken>
            <BeginDate>
                <Calendar type="Gregorian">
                    <day>10</day>
                    <month>10</month>
                    <year>2030</year>
                </Calendar>
            </BeginDate>
            <Term>4</Term>
            <DropPoint id="f33"/>
            <Customer>
                <Username>PashaBiceps</Username>
                <Password>maFriend</Password>
                <FirstName>Pasha</FirstName>
                <LastName>Biceps</LastName>
                <Email>youAreMyBrotherMyFriend@email.com</Email>
            </Customer>
        </Reservation>
    </Reservations>
    <DropPoints>
        <DropPoint id="f33">
            <Designation>Quinta das Freiras</Designation>
            <State>Free</State>
            <Location>
                <Street>Rio Tinto</Street>
                <ZipCode>4435-074</ZipCode>
                <Country>Portugal</Country>
                <Coordinates>
                    <Longitude>32</Longitude>
                    <Latitude>52</Latitude>
                </Coordinates>
            </Location>
        </DropPoint>
        <DropPoint id="g34">
            <Designation>Norte Shopping</Designation>
            <State>Free</State>
            <Location>
                <Street>Porto</Street>
                <ZipCode>4488</ZipCode>
                <Country>Portugal</Country>
                <Coordinates>
                    <Longitude>24</Longitude>
                    <Latitude>12</Latitude>
                </Coordinates>
            </Location>
        </DropPoint>
    </DropPoints>
</System>

My XSL file:

<?xml version="1.0"?>

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

    <xsl:template match="/">
        <html>
            <body>
                <h2>Customers</h2>
                <hr></hr><hr></hr>
                <!-- select="System/Reservations/Reservation/Customer" -->

                <xsl:for-each select="System/Reservations/Reservation/Customer">
                    <xsl:variable name="customerEmail" select="Email"/>

                    <h4><b>Name: </b> <xsl:value-of select="FirstName"/> <xsl:value-of select="LastName"/> </h4>
                    <h4><b>E-mail: </b> <xsl:value-of select="Email"/> </h4>

                    <!-- Creates a table with information about reservations, for each client -->
                    <table border="1">
                    <tr bgcolor="#9acd32">
                        <th>Reservation ID</th>
                        <th>Date</th>
                        <th>Duration (days)</th>
                        <th>Customer Token</th>
                    </tr>

                    <xsl:for-each select="../../Reservation">
                        <xsl:variable name="customerEmailCurrentReservation" select="Customer/Email"/>

                        <!-- processes reservations for that customer only -->
                        <xsl:if test="$customerEmail=$customerEmailCurrentReservation">

                            <tr>                                    
                                <td><xsl:value-of select="@id"/></td>
                                <td><xsl:value-of select="BeginDate/Calendar/day"/>-<xsl:value-of select="BeginDate/Calendar/month"/>-<xsl:value-of select="BeginDate/Calendar/year"/></td>
                                <td><xsl:value-of select="Term"/></td>
                                <td><xsl:value-of select="CustomerToken"/></td>
                            </tr>

                        </xsl:if>
                    </xsl:for-each>

                    </table> <!-- End of the table for that customer -->
                    <br></br><hr></hr><br></br>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>

This is what I get (in the HTML transformed file): enter image description here


And this is what I want to obtain: enter image description here

Thank you in advance!

Xavier Silva
  • 267
  • 1
  • 19
  • This is a *grouping* problem - see: http://www.jenitennison.com/xslt/grouping/muenchian.html and numerous examples of Muenchian grouping here on SO. – michael.hor257k Jun 14 '16 at 19:17
  • @michael.hor257k Thank you, I've actual tried to use that but I have some problems... If I define a key before the first for-each loop, like this ``, it says that the XSL is not valid... any help? Thank you, I'm new to XSL... – Xavier Silva Jun 14 '16 at 21:02
  • You should have posted you attempt, so we can fix it, instead of writing everything from scratch. And no - the key definition you show does **not** produce an error. – michael.hor257k Jun 14 '16 at 21:40
  • @michael.hor257k I believe the error happened because of XPATH, since the key made the `select` on the `for-each` not possible... Also, thank you for your answer, you have helped me a lot! – Xavier Silva Jun 15 '16 at 09:21

1 Answers1

1

The last thing we need is yet another example of Muenchian grouping. But since you can't seem to manage on your own, try it this way:

XSLT 1.0

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

<xsl:key name="reservation-by-customer" match="Reservation" use="Customer/Email" />

<xsl:template match="/System">
    <html>
        <body>
            <h2>Customers</h2>
            <!-- for each distinct customer -->
            <xsl:for-each select="Reservations/Reservation[count(. | key('reservation-by-customer', Customer/Email)[1]) = 1]">
                <!-- customer's details -->
                <h4>
                    <xsl:text>Name: </xsl:text>
                    <xsl:value-of select="Customer/FirstName"/>
                    <xsl:text> </xsl:text>
                    <xsl:value-of select="Customer/LastName"/>
                </h4>
                <!--  customer's reservations -->
                <table border="1">
                    <tr>
                        <th>Reservation ID</th>
                        <th>Date</th>
                        <th>Duration (days)</th>
                        <th>Customer Token</th>
                    </tr>
                    <xsl:for-each select="key('reservation-by-customer', Customer/Email)">
                        <tr>                                    
                            <td>
                                <xsl:value-of select="@id"/>
                            </td>
                            <td>
                                <xsl:value-of select="BeginDate/Calendar/day"/>
                                <xsl:text>-</xsl:text>
                                <xsl:value-of select="BeginDate/Calendar/month"/>
                                <xsl:text>-</xsl:text>
                                <xsl:value-of select="BeginDate/Calendar/year"/>
                            </td>
                            <td>
                                <xsl:value-of select="Term"/>
                            </td>
                            <td>
                                <xsl:value-of select="CustomerToken"/>
                            </td>
                        </tr>
                    </xsl:for-each>
                </table> 
                <hr/>
            </xsl:for-each>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51