Problems with foreach and SimpleXML

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
magic07
Forum Newbie
Posts: 2
Joined: Sun Mar 06, 2011 3:23 am

Problems with foreach and SimpleXML

Post by magic07 »

Hi,

I have two problems with reading a XML file with SimpleXML and the foreach loop:

Problem number one: If I have an item with only one "segment" child, I get the error "Fatal error: Call to a member function attributes() on a non-object in /var/www/readxml.php on line 28". My way of using a $segnum variable which I increment is maybe not necessary since it is a foreach loop... But what would be the right way?

Problem number two: My code only sums up the size of the first two segments, but it should sum up all. What's the problem here?

My xml file for testing looks like this:
[text]<?xml version="1.0" encoding="iso-8859-1" ?>
<xml>
<file poster="John Doe <john@example.com>" date="1301234567" subject="bla bla "filename1.zip" yEnc (1/5)">
<groups>
<group>a.b.blabla</group>
<group>a.b.dadada</group>
</groups>
<segments>
<segment bytes="100000" number="1">3e5d7d4f336475502b643b466d@example.com</segment>
<segment bytes="200000" number="2">272b5c2e3e447a66407b20633d@example.com</segment>
<segment bytes="300000" number="3">3e2724613926406d692765446e@example.com</segment>
<segment bytes="400000" number="4">213939595c6b51575c43665d48@example.com</segment>
<segment bytes="50000" number="5">3366285f6a7b317945405c3b30@example.com</segment>
</segments>
</file>
<file poster="John Doe <john@example.com>" date="1301234678" subject="bla bla "filename2.zip" yEnc (1/5)">
<groups>
<group>a.b.blabla</group>
<group>a.b.dadada</group>
</groups>
<segments>
<segment bytes="300000" number="1">2c7778262263625f7a64343137@example.com</segment>
<segment bytes="400000" number="2">78685e6e7b4339272b7042772c@example.com</segment>
<segment bytes="500000" number="3">7a47472e25265a3b6e55214e75@example.com</segment>
<segment bytes="600000" number="4">6c4e64784e70384c3e2a2a544e@example.com</segment>
<segment bytes="50000" number="5">76695f59277724334035724a22@example.com</segment>
</segments>
</file>
<file poster="John Doe <john@example.com>" date="1301234789" subject="bla bla "filename3.zip" yEnc (1/1)">
<groups>
<group>a.b.blabla</group>
<group>a.b.dadada</group>
</groups>
<segments>
<segment bytes="200000" number="1">283d4f6f384f417b422f697163@example.com</segment>
</segments>
</file>
</xml>[/text]

My PHP code:

Code: Select all

<?php

// read the xml file
$xml = simplexml_load_file('demo.xml');

// initialize helper variables
$filenum = 0;

// loop through all files
foreach($xml as $files){ 

	// get the posting date
	$timestamp = (int)$xml->file[$filenum]->attributes()->date;
	echo date("Y-m-d H:i:s", $timestamp);
	echo " - ";

	// get the filename
	$subject = $xml->file[$filenum]->attributes()->subject;
	preg_match("#.*\"(.*)\".*#iu", $subject, $matches);
	echo $matches[1];
	echo " - ";

	// loop through all segments of file to get total size
	$segnum = 0;
	$totalbytes = 0;
	foreach($xml->file[$filenum] as $segments){
		$totalbytes += $xml->file[$filenum]->segments->segment[$segnum]->attributes();
		$segnum++;
	} // end segments

echo $totalbytes;
echo "<br />\n";
$filenum++;

} // end files

?>
Current output: [text]2011-03-27 16:02:47 - filename1.zip - 300000
2011-03-27 16:04:38 - filename2.zip - 700000
2011-03-27 16:06:29 - filename3.zip -
Fatal error: Call to a member function attributes() on a non-object in /var/www/readxml.php on line 28[/text]

Thank you very much for your help!
User avatar
Darhazer
DevNet Resident
Posts: 1011
Joined: Thu May 14, 2009 3:00 pm
Location: HellCity, Bulgaria

Re: Problems with foreach and SimpleXML

Post by Darhazer »

SimpleXML offers a much simpler way to do this:

Code: Select all

<?php

// read the xml file
$xml = simplexml_load_file('demo.xml');

// loop through all files
foreach($xml as $file){ 

        // get the posting date
        $timestamp = (int)$file['date'];
        echo date("Y-m-d H:i:s", $timestamp);
        echo " - ";

        // get the filename
        $subject = $file['subject'];
        preg_match("#.*\"(.*)\".*#iu", $subject, $matches);
        echo $matches[1];
        echo " - ";

        // loop through all segments of file to get total size
        $totalbytes = 0;
        foreach($file->segments->segment as $segment){
                $totalbytes += (int)$segment['bytes'];
        } // end segments

echo $totalbytes;
echo "<br />\n";
} // end files

?>
magic07
Forum Newbie
Posts: 2
Joined: Sun Mar 06, 2011 3:23 am

Re: Problems with foreach and SimpleXML

Post by magic07 »

Awesome! This is really great, I didn't know that SimpleXML can be THAT simple!

Thank you very much!
Post Reply