SimpleXML - Sorting an XML list removes nodes with duplicate dates

26 Views Asked by At

I have a website that holds a list of events in an XML list. The client is able to edit, delete and add events using a very simple web-based editor. This is the format of the XML list...

<?xml version="1.0"?>
<eventlist>
    <event>
        <eventtype>3-Bike Experience - Full Day</eventtype>
        <location>Oulton Park, Cheshire</location>
        <explevel>All</explevel>
        <eventdate>26-07-2023</eventdate>
        <eventprice>400.00</eventprice>
        <trackprice>150.00</trackprice>
    </event>
</eventlist>

The problem I have is that whenever I sort the XML list, it removes any events that share the same date - in effect, making it impossible to list events that occur on the same day. Here is the code I am using to sort the XML list...

$eventlist = new SimpleXMLElement('events.xml', null, true);

$dateArray = array();
$eventXMLstringAray = array();

foreach ($eventlist->event as $event)
{
    $eventdate = $event->eventdate;
    $date = mktime(0,0,0,substr($eventdate,3,2),substr($eventdate,0,2),substr($eventdate,6,4));
    array_push($dateArray, $date);
    array_push($eventXMLstringAray, $event->asXML());
}
$eventXMLstringAray = array_combine($dateArray, $eventXMLstringAray);
ksort($eventXMLstringAray);
$newXMLStr = '';
foreach ($eventXMLstringAray as $eventXMLstr)
{
    $newXMLStr = $newXMLStr . $eventXMLstr;
}
$newXMLStr = '<eventlist>' . $newXMLStr . '</eventlist>';
$eventlist = simplexml_load_string($newXMLStr);
$eventlist->asXML('events.xml');

The sort code above uses the date of each event (held in $event->eventdate) as the sort key but instead of just stacking events that share the same date, it just stores the most recently added event. I am totally stuck!

1

There are 1 best solutions below

1
CBroe On

array_combine will of course overwrite array entries, if the first array of keys that you pass, contains any duplicates.

You can collect the events in a sub-array below the date first to avoid that:

$eventXMLstringArray = array();
foreach ($eventlist->event as $event)
{
    $eventdate = $event->eventdate;
    $date = mktime(0,0,0,substr($eventdate,3,2),substr($eventdate,0,2),substr($eventdate,6,4));
    $eventXMLstringArray[$date][] = $event->asXML();
}
ksort($eventXMLstringArray);
$newXMLStr = '';
foreach ($eventXMLstringArray as $eventXML)
{
    $newXMLStr .= implode('', $eventXML);
}

$eventXML in your second loop will always be an array now - containing one, or multiple events. implode with an empty string as separator will concatenate them together as one string.