<?xml version="1.0" encoding="utf-8"?>
<Agenda>
<responseMessage>Success.</responseMessage>
<jobs>
<trip>
<header>
<reservation_number>10562</reservation_number>
<recipient_first>John</recipient_first>
<recipient_middle>H</recipient_middle>
<recipient_last>Doe</recipient_last>
</header>
<legs>
<leg>
<trip_id>42390</trip_id>
<leg_status>Active</leg_status>
<pickup_date>12/24/2020</pickup_date>
<pickup_time>0600</pickup_time>
<pickup_state>New York</pickup_state>
<pickup_country>USA</pickup_country>
<dropoff_state>Pennsylvania</dropoff_state>
<dropoff_country>USA</dropoff_country>
</leg>
<leg>
<trip_id>42391</trip_id>
<leg_status>Canceled</leg_status>
<pickup_date>01/02/2021</pickup_date>
<pickup_time>1800</pickup_time>
<pickup_state>Pennsylvania</pickup_state>
<pickup_country>USA</pickup_country>
<dropoff_state>New York</dropoff_state>
<dropoff_country>USA</dropoff_country>
</leg>
</legs>
<secondary_services>
<service>
<service_leg_id>42390</service_leg_id>
<service_name>Tolls</service_name>
<service_rate>3.00</service_rate>
<service_quantity>1</service_quantity>
</service>
<service>
<service_leg_id>42390</service_leg_id>
<service_name>addtl.miles</service_name>
<service_rate>3.40</service_rate>
<service_quantity>25</service_quantity>
</service>
<service>
<service_leg_id>42391</service_leg_id>
<service_name>Tolls</service_name>
<service_rate>18.00</service_rate>
<service_quantity>1</service_quantity>
</service>
<service>
<service_leg_id>42391</service_leg_id>
<service_name>addtl.miles</service_name>
<service_rate>3.40</service_rate>
<service_quantity>29</service_quantity>
</service>
</secondary_services>
</trip>
<trip>
<header>
<reservation_number>10575</reservation_number>
<recipient_first>Emily</recipient_first>
<recipient_middle></recipient_middle>
<recipient_last>Santana</recipient_last>
</header>
<legs>
<leg>
<trip_id>64593</trip_id>
<leg_status>Active</leg_status>
<pickup_date>12/27/2020</pickup_date>
<pickup_time>1700</pickup_time>
<pickup_state>New York</pickup_state>
<pickup_country>USA</pickup_country>
<dropoff_state>Connecticut</dropoff_state>
<dropoff_country>USA</dropoff_country>
</leg>
<leg>
<trip_id>64594</trip_id>
<leg_status>Active</leg_status>
<pickup_date>01/04/2021</pickup_date>
<pickup_time>1200</pickup_time>
<pickup_state>Connecticut</pickup_state>
<pickup_country>USA</pickup_country>
<dropoff_state>New York</dropoff_state>
<dropoff_country>USA</dropoff_country>
</leg>
</legs>
<secondary_services>
<service>
<service_leg_id>64593</service_leg_id>
<service_name>Tolls</service_name>
<service_rate>0.00</service_rate>
<service_quantity>0</service_quantity>
</service>
<service>
<service_leg_id>64593</service_leg_id>
<service_name>addtl.miles</service_name>
<service_rate>3.40</service_rate>
<service_quantity>10</service_quantity>
</service>
<service>
<service_leg_id>64594</service_leg_id>
<service_name>Tolls</service_name>
<service_rate>04.00</service_rate>
<service_quantity>1</service_quantity>
</service>
<service>
<service_leg_id>64594</service_leg_id>
<service_name>addtl.miles</service_name>
<service_rate>3.40</service_rate>
<service_quantity>11</service_quantity>
</service>
</secondary_services>
</trip>
</jobs>
</Agenda>
I am having trouble looping through an foreach loop to output a table such as this one.
Reservation ID | Status | Name | Date | Time | PU Location | DO Location | Tolls | Addlt. Miles |
---|---|---|---|---|---|---|---|---|
10562-42390 | Active | John H Doe | 12/24/2020 | 0600 | New York, USA | Pennsylvania, USA | 3.00 | 25 |
10562-42391 | Canceled | John H Doe | 01/02/2021 | 1800 | Pennsylvania, USA | New York, USA | 18.00 | 29 |
10575-64593 | Active | Emily Santana | 12/27/2020 | 1700 | New York, USA | Connecticut, USA | 0.00 | 10 |
10575-64594 | Active | Emily Santana | 01/04/2021 | 1200 | Connecticut, USA | New York, USA | 4.00 | 11 |
I've tried a foreach loop with keys and values inside another foreach loop but I was unable to match the service element with the leg element as they have their independent loops.
Consider XSLT, the special-purpose language designed to transform XML files such as handling all the concatenation of values and matching of leg ids. If needed, XSLT can even convert to HTML. PHP can run XSLT 1.0 scripts with its xsl class using DOMDocument
library.
XSLT (save as .xsl file, a special .xml file)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="leg_key" match="leg" use="trip_id" />
<xsl:template match="/Agenda">
<xsl:copy>
<xsl:apply-templates select="descendant::leg[generate-id() =
generate-id(key('leg_key', trip_id)[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="leg">
<xsl:copy>
<xsl:variable name="curr_leg_id" select="trip_id"/>
<Reservation_id>
<xsl:value-of select="concat(ancestor::trip/header/reservation_number, '-', trip_id)"/>
</Reservation_id>
<Status><xsl:value-of select="leg_status"/></Status>
<Name><xsl:value-of select="concat(ancestor::trip/header/recipient_first, ' ',
ancestor::trip/header/recipient_middle, ' ',
ancestor::trip/header/recipient_last)"/></Name>
<Date><xsl:value-of select="pickup_date"/></Date>
<Time><xsl:value-of select="pickup_time"/></Time>
<PU_location><xsl:value-of select="concat(pickup_state, ' ', pickup_country)"/></PU_location>
<DO_location><xsl:value-of select="concat(dropoff_state, ' ', dropoff_country)"/></DO_location>
<Tolls>
<xsl:value-of select="ancestor::trip/secondary_services/service[service_leg_id = $curr_leg_id and
service_name='Tolls']/service_rate"/>
</Tolls>
<Addl>
<xsl:value-of select="ancestor::trip/secondary_services/service[service_leg_id = $curr_leg_id and
service_name='addtl.miles']/service_quantity"/>
</Addl>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
PHP (use $new_xml
for final end-use needs)
// LOAD XML
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->load('/path/to/Input.xml');
// LOAD XSLT
$xsl = new DOMDocument('1.0', 'UTF-8');
$xsl->load('/path/to/XSLT_Script.xsl');
// INITIALIZE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
// TRANSFORM ORIGINAL DOCUMENT
$new_xml = $proc->transformToDoc($xml);
// ECHO TO SCREEN
echo $new_xml->saveXML();
// SAVE TO FILE
file_put_contents('/path/to/Output.xml', $new_xml);