Hi Colin.
Let me start off by apologising in advance for the length of this post; there is a lot to read, far more than you really need.
To begin, I’d like to introduce some concepts that you might or might not be familiar with, which are vital to understanding SimpleXML and how it does its magic (in a very real sense of the word!).
One of those concepts is that of the iterable object. That is a fancy word for being able to loop (iterate) over a collection of things, like you would with an array (the term applies for arrays, “boring” objects and iterable ones too). The foreach
loop is easy to make sense of: it runs the code inside it for each item in the thing being looped. That thing can be an array, in which case the code runs once for each item in the array. It can be what I’ll call a “boring” object, though this is less used, and the code runs for each (visible) property of that object. And finally, it can be an iterable object, and the code runs for each item within it (what exactly an “item” is, can vary wildly).
Bringing this into the world of SimpleXML, a SimpleXMLElement object is one of those fancy objects! There is a whole world of magic happening for this particular class and I won’t pretend to list it all, just some key points. With reference to iterable objects, SimpleXMLElements most certainly are! A good point to keep in mind is that in XML, there can be multiple elements at any one level with the same name, so how does that translate into SimpleXML-land? Lets have an example:
<?php
$xml = "
<album>
<song>A Kind of Magic</song>
<song>Under Pressure</song>
<song>Radio Ga Ga</song>
</album>
";
$sxe = new SimpleXMLElement($xml);
echo $sxe->song;
// Outputs: A Kind of Magic
So, we access the song information by its tag name. $sxe
is the main album
element, and the first song can be accessed via a fake song
property. As if this wasn’t enough of a cheat (to make life “simple”!) what that really does is tells SimpleXML to return the first song
belonging to $sxe
. So how to get at the other song
s? With a loop? Well, of course that is one way but lets hold that thought for a minute.
That same, first, song
element could be pulled from the album
by accessing it with array-like notation (aside: the same way as accessing attributes for the album): like, $sxe->song[0]
.
echo $sxe->song[0] . " " . $sxe->song[2];
// Outputs: A Kind of Magic Radio Ga Ga
Hopefully, this can give a clue as to why looping over the songs would work. With a for each loop like below, the code is executed on the first, second and then third song in turn.
// This might look weird, but think about it.
$songs = $sxe->song;
foreach ($songs as $song) {
echo $song . "\
";
}
// Outputs:
// A Kind of Magic
// Under Pressure
// Radio Ga Ga
Huh, what? How can accessing the first song work within the foreach loop? This where you have to remember that the basic $parent->child
style of code accesses all of the elements (belonging to $parent
) with that name when you want to loop (or count()
, or do anything with the collection of elements) and only the first element if you want to do things like echo the content, or an attribute, or add another element to it.
So how does all this relate to the topic? Lets take a look. The basic outline is that there are two property
elements within the top-level root
element. Each of those property
elements has both a single id
and images
element. So, it looks like the example below (the contents of images
are removed so that you can see the described structure).
<root>
<property>
<id>153</id>
<images>...</images>
</property>
<property>
<id>154</id>
<images>...</images>
</property>
</root>
To loop over each of the property
elements and access their respective id
, as has already been posted in the thread, we can do:
foreach ($feed->property as $property) {
echo $property->id . "\
"; // $property->id[0] would work too
}
// Outputs:
// 153
// 154
To loop over the collection of image
s (within the images
element) for each property
, you can do the following:
foreach ($feed->property as $property) {
foreach ($property->images->image as $image) {
// Do something useful here
}
}
Each image
looks like the snippet below, with different values of course.
<image id="1">
<url>http://www.mysite.com/product/images/1322.jpg</url>
<title>
<en>Title 1</en>
</title>
</image>
To get at the url
element, you can simply use $image->url
but remember that that returns the SimpleXMLElement object not the text within it. To get at the text, some more magic can be employed by asking the object for its string value.
// Automagically echoes the string value
echo $image->url;
// or, see http://php.net/string#language.types.string.casting
$string_url = (string) $image->url;
Lets get to a stage where your loops are in place and you can access the values that you want (the property
id
and image
url
).
foreach($feed->property as $property) {
$id = (int) $property->id[0];
foreach ($property->images->image as $image) {
$url = (string) $image->url;
// Do something with each url and id!
echo $id . " " . $url . "\
";
}
}
// Outputs:
// 153 http://www.mysite.com/product/images/1322.jpg
// 153 http://www.mysite.com/product/images/1321.jpg
// 153 http://www.mysite.com/product/images/1316.jpg
// 154 http://www.mysite.com/product/images/1322.jpg
// 154 http://www.mysite.com/product/images/1321.jpg
// 154 http://www.mysite.com/product/images/1316.jpg
All that is really left is first of all, to go back and read all of this again! Then, plug in the building of your $sql
string at the right place. Good luck.
P.S. If all I’ve done is confuddle you, then I apologise! 