Reputation: 77
I am stock with this XML problem, I have a XML file that I browse to find values. Everything is working fine, I can read on all the child nodes, but I am stuck on this section. The XML portion containing photos are all the same name of the node, except for an attribute, how can I specify how to browse according to this and take the filename value of each of them
XML
...
<Engine>
<Fuel>Unleaded</Fuel>
<Cylinders>4</Cylinders>
<Induction>Normally aspirated</Induction>
</Engine>
<Photo order="1">
<Filename>http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_2.jpg</Filename>
</Photo>
<Photo order="2">
<Filename>http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_3.jpg</Filename>
</Photo>
<Photo order="3">
<Filename>http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_4.jpg</Filename>
</Photo>
<Photo order="4">
<Filename>http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_5.jpg</Filename>
</Photo>
<Photo order="5">
<Filename>http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_6.jpg</Filename>
...
In my php file, I have this code that help me find the values:
$import->stock_no =(string)$item->Invoice->Vehicle->VehicleStock;
$import->image1 =(string)$item->Invoice->Vehicle->Photo->attributes(order="1")->Filename;
Of course it doesn't work, how can I browse all the photo nodes( I have 8 pictures I need to take the values from)
I want to have $import->image1 = (filename in the attibutes of pohoto 1), sames for image 2, 3, etc.
Thank you.
Upvotes: 0
Views: 448
Reputation: 6625
sweet and simple with xpath
:
$xml = simplexml_load_string($x); // assume XML in $x
$photos = $xml->xpath("//Photo"); // select all Photo nodes and their children in an array
foreach ($photos as $photo)
echo "order: $photo[order], file: $photo->Filename<br />"; // simple output
see it working: http://3v4l.org/SJmEg
Upvotes: 0
Reputation: 197832
What you try to achieve is (first of all) possible by using an xpath query. You want to access a child-node based on an attribute value. The better reference questions in SimpleXML are:
It's also since some days when the suggestion was given to extend form SimpleXMLElement
to provide a utility function to actually do that with an easy interface:
However your case is a little different because of the syntax you suggest:
$xml = simplexml_load_string($buffer, 'MySimpleXMLElement');
echo $xml->Vehicle->Photo->attribute("order", "1")->Filename;
// prints "http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_2.jpg"
Instead of using an ordinary SimpleXMLElement
this example uses an extended one named (exemplary) MySimpleXMLElement
. It runs an XPath query inside based on the input parameters and based on the parent element it operates on (here being a Photo
element):
/**
* Class MySimpleXMLElement
*
* Example of how to magically access named child-nodes based
* on an attribute value of theirs.
*/
class MySimpleXMLElement extends SimpleXMLElement
{
public function attribute($name, $value) {
$nodes = $this->xpath(
sprintf('../%s[@%s = "%s"]', $this->getName(), $name, $value)
);
return $nodes ? $nodes[0] : NULL;
}
}
This new MySimpleXMLElement::attribute()
method (sorry attributes()
was already in use) is then available on every node. So have fun.
Naturally you can also write it this way:
$xml = simplexml_load_string($buffer);
echo $xml->Vehicle->xpath('Photo[@order="1"]')[0]->Filename;
// prints "http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_2.jpg"
the extended SimpleXMLElement is mainly for convenience reasons. And it's probably more easy to debug in case you're not fluent with Xpath yet.
Last time I extended SimpleXMLElement on Stackoverflow was in the said answer to the "simplexml_load_file - redundant element with empty value is converted to new SimpleXMLElement Object" question.
Upvotes: 1
Reputation: 8726
Try this
<?php
$xml = '<Engine>
<Fuel>Unleaded</Fuel>
<Cylinders>4</Cylinders>
<Induction>Normally aspirated</Induction>
</Engine>
<Photo order="1">
<Filename>http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_2.jpg</Filename>
</Photo>
<Photo order="2">
<Filename>http://usedcarpics.s3.amazonaws.com/514SPINELLITOYOTA2/b5092588_3.jpg</Filename>
</Photo>';
$xml="<Wraper>".$xml."</Wraper>";
$parse=new SimpleXMLElement($xml);
echo "Engine Fuel:".$parse->Engine->Fuel;
echo "<br/>Engine Cylinders:".$parse->Engine->Cylinders;
echo "Photos<br/>";
foreach ($parse->Photo as $photo)
{
echo "<br/>Photo Order: ".$photo->attributes();
echo "<br/>Photo URL: ".$photo->Filename;
echo "<hr/>";
}
?>
Upvotes: 0