Search code examples
phpxmlforeachsimplexml

put info of xml in array using simpleXML php


sources:

display data from XML using php simplexml

Get attributes and values using SimpleXML

PHP SimpleXML + Get Attribute

i am trying to work with the simpleXML for php but cant get it to work

my xml sample

    <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
    <gpx creator="Ski Tracks 1.3.3" version="1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
    <metadata>
    <link href="http://www.corecoders.com">
    <text>Core Coders Ltd</text>
    </link>
    <time>2012-11-15T13:52:46.005+01:00</time>
    <bounds maxlat="52.0502500" maxlon="5.6405950" minlat="52.0498680" minlon="5.6387020"/>
    </metadata>
    <trk>
    <name>New Track Doe Maar</name>
    <desc>Yeah</desc>
    <type>snowboarding</type>
    <trkseg>
    <trkpt lat="52.0499970" lon="5.6387520">
    <ele>3.00</ele>
    <time>2012-11-15T13:42:17.380+01:00</time>
    </trkpt>
    <trkpt lat="52.0499510" lon="5.6388820">
    <ele>3.00</ele>
    <time>2012-11-15T13:43:32.433+01:00</time>
    </trkpt
</trkpt>
</trkseg>
</trk>
 </gpx>

i want to retrieve the 'trkpt' attributes and their children like 'time' and 'ele' and i want to put the trkpt 'lat'/'lon', 'time' and 'ele' elements in an array. i just dont get it to work this piece is working fine now and gets the metadata info

    $xml = simplexml_load_file("./data/ski1/skitrack.xml");


    //$url = './data/ski1/skitrack.xml';
    //$xml = new SimpleXmlElement($url, null, true);

    $time = $xml->metadata[0]->time;
    $name = $xml->trk->name;
    $desc = $xml->trk->desc;
    $type = $xml->trk->type;
    foreach ($xml->metadata[0]->bounds as $bounds) {
        $maxlat = $bounds->attributes()->maxlat;
        $maxlon = $bounds->attributes()->maxlon;
        $minlat = $bounds->attributes()->minlat;
        $minlon = $bounds->attributes()->minlon; 

    }

but when i try it for the trkpt it gives me an error that there is no array: Invalid argument supplied for foreach

    print_r($xml);


    foreach ($xml->trkseg->trkpt as $trkpt) {
        $lon = $trkpt->attributes()->lon;
    }

i am actually trying to translate a code from javascript to php and it works just fine in javascr

        var alat = new Array();
        var alon = new Array();
        var ele = new Array();
        var year = new Array();
        var month = new Array();
        var day = new Array();
        var hours = new Array();
        var minutes = new Array();
        var seconds = new Array();
        var milisec = new Array();

        $(xml).find('trkseg').each(function(){
            $(this).find('trkpt').each(function(i){
                alat[i] = $(this).attr('lat');
                alon[i] = $(this).attr('lon');
                ele[i] = $(this).find('ele').text();
                year[i] = $(this).find('time').text().substr(0,4);
                month[i] = $(this).find('time').text().substr(5,2);
                day[i] = $(this).find('time').text().substr(8,2);
                hours[i] = $(this).find('time').text().substr(11,2);
                minutes[i] = $(this).find('time').text().substr(14,2);
                seconds[i] = $(this).find('time').text().substr(17,2);
                milisec[i] = $(this).find('time').text().substr(20,3);

                if(i > 0) {
                    var laterdate = new Date(year[i],month[i],day[i],hours[i],minutes[i],seconds[i],milisec[i]);
                    var earlierdate = new Date(year[i-1],month[i-1],day[i-1],hours[i-1],minutes[i-1],seconds[i-1],milisec[i-1]);
                    locDistance(alat[i-1], alon[i-1], alat[i], alon[i]);
                    timeDifference(laterdate,earlierdate);
                }

                $('.content').append(i);
                $('.content').append(
                '<br />lat ' + alat[i] +
                '<br />' + 'lon ' + alon[i] +
                '<br / >' + 'ele ' + ele[i] +
                '<br / >' + 'time ' + year[i] + (month[i]-1) + day[i] + hours[i] + minutes[i] + seconds[i] + milisec[i] +
                '<br / >' + 'dist ' + d + '<br / >'
                );

                i = i + 1;

            });
        });

thank you in advance


Solution

  • Although the xml you posted does not validate (it is missing tags), I am going to assume it should be this:

    <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
    <gpx creator="Ski Tracks 1.3.3" version="1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
       <metadata>
          <link href="http://www.corecoders.com">
             <text>Core Coders Ltd</text>
          </link>
          <time>2012-11-15T13:52:46.005+01:00</time>
          <bounds maxlat="52.0502500" maxlon="5.6405950" minlat="52.0498680" minlon="5.6387020"/>
       </metadata>
       <trk>
          <name>New Track Doe Maar</name>
          <desc>Yeah</desc>
          <type>snowboarding</type>
          <trkseg>
             <trkpt lat="52.0499970" lon="5.6387520">
                <ele>3.00</ele>
                <time>2012-11-15T13:42:17.380+01:00</time>
             </trkpt>
             <trkpt lat="52.0499510" lon="5.6388820">
                <ele>3.00</ele>
                <time>2012-11-15T13:43:32.433+01:00</time>
             </trkpt>
          </trkseg>
       </trk>
    </gpx>
    

    If that is the case, then your code that says foreach ($xml->trkseg->trkpt is unable to find the trkseg since it is nested within the trk element. Instead you could try to go through each trk element and within each trk element you can then access the trkseg elements.

    foreach($xml->trk as $trk)
    {
        //do something with each trk
    
        foreach ($trk->trkseg->trkpt as $trkpt) {
    
             //do something with each trkseg
    
        }
    }