php - How to parse xml with xpath and retrieve an array of elements?
I'm trying to get this thing done for about 3 hours so I would appreciate any help. I need to parse the xml below and extract the 'title', 'description', 'phone', 'address', 'price', 'pictures', 'attributes'. I've managed to extract the title, description and phone.
I can't get the address(location) latitude and longitude individually. I get -1.3054552.7008 instead of latitude: -1.3054, longitude: 552.7008.
I don't know how to extract the pictures. It should be an array.
I don't know how to extract the attributes. It should be an array.
Here is the code I have:
$adXml = file_get_contents('ad.xml');
$dom = new DOMDocument();
$dom->loadXml($adXml);
$xpath = new DOMXpath($dom);
$xpath->registerNamespace('ad', 'http://www.domainclassifiedsgroup.com/schema/ad/v1');
$xpath->registerNamespace('attribute', 'http://www.domainclassifiedsgroup.com/schema/attribute/v1');
$xpath->registerNamespace('pic', 'http://www.domainclassifiedsgroup.com/schema/picture/v1');
$xpath->registerNamespace('location', 'http://www.domainclassifiedsgroup.com/schema/location/v1');
#$ads = $xpath->evaluate('/ad:ad/ad:ad', NULL, FALSE);
$title = $xpath->evaluate('string(ad:title)', NULL, FALSE);
$description = $xpath->evaluate('string(ad:description)', NULL, FALSE);
$phone = $xpath->evaluate('string(ad:phone)', NULL, FALSE);
//the price is a kind of array so we ened to remove GBP
$price = $xpath->evaluate('string(ad:price)', NULL, FALSE);
$price = str_replace('GBP', '', $price);
//$pictures = $xpath->evaluate('string(pic:pictures)', NULL, FALSE);
$pictures = '?';
$attributes = '?';
$address = $xpath->evaluate('string(ad:ad-address)', NULL, FALSE); // why is not array ?
The xml is below
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ad:ad xmlns:types="http://www.domainclassifiedsgroup.com/schema/types/v1" xmlns:cat="http://www.domainclassifiedsgroup.com/schema/category/v1" xmlns:loc="http://www.domainclassifiedsgroup.com/schema/location/v1" xmlns:ad="http://www.domainclassifiedsgroup.com/schema/ad/v1" xmlns:feat="http://www.domainclassifiedsgroup.com/schema/feature/v1" xmlns:attr="http://www.domainclassifiedsgroup.com/schema/attribute/v1" xmlns:pic="http://www.domainclassifiedsgroup.com/schema/picture/v1" xmlns:user="http://www.domainclassifiedsgroup.com/schema/user/v1" xmlns:rate="http://www.domainclassifiedsgroup.com/schema/rate/v1" xmlns:reply="http://www.domainclassifiedsgroup.com/schema/reply/v1" xmlns:feed="http://www.domainclassifiedsgroup.com/schema/feed/v1" xmlns:order="http://www.domainclassifiedsgroup.com/schema/order/v1" xmlns:payment="http://www.domainclassifiedsgroup.com/schema/payment/v1" locale="en_GB" version="1.17" id="1047060901">
<ad:price>
<types:currency-iso-code>
<types:value localized-label="£">GBP</types:value>
</types:currency-iso-code>
<types:amount>17300</types:amount>
</ad:price>
<ad:title>BMW 330d M Sport Highline Coupe Black Diesel Auto + RED LEATHER</ad:title>
<ad:description>2009 (59-reg). Sapphire black metallic. Coral red Dakota leather, electric adjustable seats with memory, heated seats, sport seats, USB interface for iPod, steering wheel gear shift, Angel daytime running lights, Xenon headlights, 19 inch Double spoke alloy wheels, fine brushed aluminium interior trim, power fold mirrors, M Sport Aerodynamic bodystyling package, loudspeaker audio upgrade, enhanced Bluetooth, climate control, cruise control, trip computer, ISOFIX child seat anchors, park sensors, split folding rear seats, remote locking alarm. FSH.
Passenger Airbag; Air Conditioning; Premium Sound System; AM/FM Stereo; Xenon headlights; Climate Control; Alloy Wheels; Full Service History; Alarm; Tilt Steering Wheel; Central Locking; Anti-Lock Brakes (ABS); CD Player; Driver Airbag; Electric Windows; Power-assisted Steering (PAS); Electric heated seats; Safety Belt Pretensioners; Parking Sensors; V5 Registration Document; Cruise Control; Leather Seats; Immobiliser; Electric Adjustable Seats; Side Airbags; Rear seat belts; Electronic Stability Program (ESP) </ad:description>
<ad:ad-address>
<types:longitude>-1.30545</types:longitude>
<types:latitude>52.7008</types:latitude>
</ad:ad-address>
<ad:search-distance>
<ad:display-distance></ad:display-distance>
</ad:search-distance>
<ad:ad-status>
<ad:value>ACTIVE</ad:value>
</ad:ad-status>
<ad:email>EXIST</ad:email>
<ad:user-id>3463331380</ad:user-id>
<ad:poster-ip-address/>
<ad:phone>01530249618</ad:phone>
<ad:modification-date-time>2014-02-02T03:02:41.000Z</ad:modification-date-time>
<ad:start-date-time>2014-02-02T03:02:41.000Z</ad:start-date-time>
<feat:features-active>
<feat:feature-active display="true" name="AD_INSERTION" group="standard"/>
</feat:features-active>
<cat:category id="10303">
<cat:id-name>bmw</cat:id-name>
<cat:localized-name>BMW</cat:localized-name>
<cat:categoriesTree/>
</cat:category>
<loc:locations>
<loc:location id="10000393">
<loc:id-name>england</loc:id-name>
<loc:localized-name>England</loc:localized-name>
<loc:parent-id/>
<loc:location-breadcrumb/>
</loc:location>
<loc:location id="10000392">
<loc:id-name>uk</loc:id-name>
<loc:localized-name>United Kingdom</loc:localized-name>
<loc:parent-id/>
<loc:location-breadcrumb/>
</loc:location>
<loc:location id="11000025">
<loc:id-name>leicestershire</loc:id-name>
<loc:localized-name>Leicestershire</loc:localized-name>
<loc:parent-id/>
<loc:location-breadcrumb/>
</loc:location>
</loc:locations>
<ad:neighborhood></ad:neighborhood>
<attr:attributes>
<attr:attribute localized-label="Fuel type" type="ENUM" name="vehicle_fuel_type">
<attr:value localized-label="Diesel">diesel</attr:value>
</attr:attribute>
<attr:attribute localized-label="Year" type="INTEGER" name="vehicle_registration_year">
<attr:value localized-label="2009">2009</attr:value>
</attr:attribute>
<attr:attribute localized-label="Body type" type="ENUM" name="vehicle_body_type">
<attr:value localized-label="Coupe">coupe</attr:value>
</attr:attribute>
<attr:attribute localized-label="Model" type="STRING" name="vehicle_model">
<attr:value>330</attr:value>
</attr:attribute>
<attr:attribute localized-label="Colour" type="STRING" name="vehicle_colour">
<attr:value>Black</attr:value>
</attr:attribute>
<attr:attribute localized-label="Seller type" type="ENUM" name="seller_type">
<attr:value localized-label="Trade">trade</attr:value>
</attr:attribute>
<attr:attribute localized-label="Mileage" type="LONG" name="vehicle_mileage">
<attr:value>65000</attr:value>
</attr:attribute>
<attr:attribute localized-label="Transmission" type="ENUM" name="vehicle_transmission">
<attr:value localized-label="Automatic">automatic</attr:value>
</attr:attribute>
<attr:attribute localized-label="Make" type="ENUM" name="vehicle_make">
<attr:value localized-label="BMW">bmw</attr:value>
</attr:attribute>
<attr:attribute localized-label="Engine size" type="LONG" name="vehicle_engine_size">
<attr:value>2993</attr:value>
</attr:attribute>
</attr:attributes>
<ad:link rel="self" href="https://iphone-api.zmbtree.com/api/ads/1047060901"/>
<ad:link rel="self-user" href="https://iphone-api.zmbtree.com/api/users/3463331380/ads/1047060901"/>
<ad:link rel="self-public-website" href="http://www.zmbtree.com/p/cars-vans-motorbikes/bmw-330d-m-sport-highline-coupe-black-diesel-auto-red-leather/1047060901"/>
<pic:pictures>
<pic:picture>
<pic:link rel="extrabig" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/C-QAAMXQWzNSeR-h/$(KGrHqJHJFEFJ0Ie)pzWBSeR-hK5zw~~48_80.JPG"/>
<pic:link rel="preview" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/C-QAAMXQWzNSeR-h/$(KGrHqJHJFEFJ0Ie)pzWBSeR-hK5zw~~48_81.JPG"/>
<pic:link rel="big" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/C-QAAMXQWzNSeR-h/$(KGrHqJHJFEFJ0Ie)pzWBSeR-hK5zw~~48_79.JPG"/>
<pic:link rel="thumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/C-QAAMXQWzNSeR-h/$(KGrHqJHJFEFJ0Ie)pzWBSeR-hK5zw~~48_78.JPG"/>
<pic:link rel="moreadsthumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/C-QAAMXQWzNSeR-h/$(KGrHqJHJFEFJ0Ie)pzWBSeR-hK5zw~~48_77.JPG"/>
</pic:picture>
<pic:picture>
<pic:link rel="extrabig" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/rwcAAOxyLN9SeR-h/$(KGrHqNHJEIFJbuUsB1BBSeR-hFuC!~~48_80.JPG"/>
<pic:link rel="preview" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/rwcAAOxyLN9SeR-h/$(KGrHqNHJEIFJbuUsB1BBSeR-hFuC!~~48_81.JPG"/>
<pic:link rel="big" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/rwcAAOxyLN9SeR-h/$(KGrHqNHJEIFJbuUsB1BBSeR-hFuC!~~48_79.JPG"/>
<pic:link rel="thumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/rwcAAOxyLN9SeR-h/$(KGrHqNHJEIFJbuUsB1BBSeR-hFuC!~~48_78.JPG"/>
<pic:link rel="moreadsthumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/rwcAAOxyLN9SeR-h/$(KGrHqNHJEIFJbuUsB1BBSeR-hFuC!~~48_77.JPG"/>
</pic:picture>
<pic:picture>
<pic:link rel="extrabig" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/DKgAAOxyzi9SeR-h/$T2eC16F,!yEFI9U4HtWeBSeR-h!PI!~~48_80.JPG"/>
<pic:link rel="preview" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/DKgAAOxyzi9SeR-h/$T2eC16F,!yEFI9U4HtWeBSeR-h!PI!~~48_81.JPG"/>
<pic:link rel="big" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/DKgAAOxyzi9SeR-h/$T2eC16F,!yEFI9U4HtWeBSeR-h!PI!~~48_79.JPG"/>
<pic:link rel="thumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/DKgAAOxyzi9SeR-h/$T2eC16F,!yEFI9U4HtWeBSeR-h!PI!~~48_78.JPG"/>
<pic:link rel="moreadsthumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/DKgAAOxyzi9SeR-h/$T2eC16F,!yEFI9U4HtWeBSeR-h!PI!~~48_77.JPG"/>
</pic:picture>
<pic:picture>
<pic:link rel="extrabig" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/p-QAAOxypNtSeR-h/$T2eC16VHJG8E9nyfnfl1BSeR-hFy)!~~48_80.JPG"/>
<pic:link rel="preview" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/p-QAAOxypNtSeR-h/$T2eC16VHJG8E9nyfnfl1BSeR-hFy)!~~48_81.JPG"/>
<pic:link rel="big" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/p-QAAOxypNtSeR-h/$T2eC16VHJG8E9nyfnfl1BSeR-hFy)!~~48_79.JPG"/>
<pic:link rel="thumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/p-QAAOxypNtSeR-h/$T2eC16VHJG8E9nyfnfl1BSeR-hFy)!~~48_78.JPG"/>
<pic:link rel="moreadsthumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/p-QAAOxypNtSeR-h/$T2eC16VHJG8E9nyfnfl1BSeR-hFy)!~~48_77.JPG"/>
</pic:picture>
<pic:picture>
<pic:link rel="extrabig" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/AhMAAOxy4t1SeR~d/$T2eC16h,!z!FJ4!MUtWSBSeR+d8SCw~~48_80.JPG"/>
<pic:link rel="preview" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/AhMAAOxy4t1SeR~d/$T2eC16h,!z!FJ4!MUtWSBSeR+d8SCw~~48_81.JPG"/>
<pic:link rel="big" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/AhMAAOxy4t1SeR~d/$T2eC16h,!z!FJ4!MUtWSBSeR+d8SCw~~48_79.JPG"/>
<pic:link rel="thumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/AhMAAOxy4t1SeR~d/$T2eC16h,!z!FJ4!MUtWSBSeR+d8SCw~~48_78.JPG"/>
<pic:link rel="moreadsthumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/AhMAAOxy4t1SeR~d/$T2eC16h,!z!FJ4!MUtWSBSeR+d8SCw~~48_77.JPG"/>
</pic:picture>
<pic:picture>
<pic:link rel="extrabig" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjkAAOxy3NBSeR~e/$(KGrHqN,!rkFJURnmyKpBSeR+eQ7Rg~~48_80.JPG"/>
<pic:link rel="preview" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjkAAOxy3NBSeR~e/$(KGrHqN,!rkFJURnmyKpBSeR+eQ7Rg~~48_81.JPG"/>
<pic:link rel="big" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjkAAOxy3NBSeR~e/$(KGrHqN,!rkFJURnmyKpBSeR+eQ7Rg~~48_79.JPG"/>
<pic:link rel="thumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjkAAOxy3NBSeR~e/$(KGrHqN,!rkFJURnmyKpBSeR+eQ7Rg~~48_78.JPG"/>
<pic:link rel="moreadsthumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjkAAOxy3NBSeR~e/$(KGrHqN,!rkFJURnmyKpBSeR+eQ7Rg~~48_77.JPG"/>
</pic:picture>
<pic:picture>
<pic:link rel="extrabig" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/x9YAAOxyXDhSeR~e/$(KGrHqFHJB8FJvCbFiKMBSeR+elk(Q~~48_80.JPG"/>
<pic:link rel="preview" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/x9YAAOxyXDhSeR~e/$(KGrHqFHJB8FJvCbFiKMBSeR+elk(Q~~48_81.JPG"/>
<pic:link rel="big" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/x9YAAOxyXDhSeR~e/$(KGrHqFHJB8FJvCbFiKMBSeR+elk(Q~~48_79.JPG"/>
<pic:link rel="thumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/x9YAAOxyXDhSeR~e/$(KGrHqFHJB8FJvCbFiKMBSeR+elk(Q~~48_78.JPG"/>
<pic:link rel="moreadsthumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/x9YAAOxyXDhSeR~e/$(KGrHqFHJB8FJvCbFiKMBSeR+elk(Q~~48_77.JPG"/>
</pic:picture>
<pic:picture>
<pic:link rel="extrabig" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjUAAOxy3NBSeR~d/$(KGrHqMOKpIFJ30nYMeqBSeR+e!FDg~~48_80.JPG"/>
<pic:link rel="preview" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjUAAOxy3NBSeR~d/$(KGrHqMOKpIFJ30nYMeqBSeR+e!FDg~~48_81.JPG"/>
<pic:link rel="big" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjUAAOxy3NBSeR~d/$(KGrHqMOKpIFJ30nYMeqBSeR+e!FDg~~48_79.JPG"/>
<pic:link rel="thumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjUAAOxy3NBSeR~d/$(KGrHqMOKpIFJ30nYMeqBSeR+e!FDg~~48_78.JPG"/>
<pic:link rel="moreadsthumb" href="http://i.domainimg.com/00/s/NTMxWDgwMA==/z/MjUAAOxy3NBSeR~d/$(KGrHqMOKpIFJ30nYMeqBSeR+e!FDg~~48_77.JPG"/>
</pic:picture>
</pic:pictures>
<ad:visible-on-map>true</ad:visible-on-map>
<ad:poster-contact-email>EXIST</ad:poster-contact-email>
<ad:poster-contact-name/>
</ad:ad>
Update : Trying to retrieve the images using
$pictures = $xml->xpath("//pic:pictures/pic:picture");
foreach ($pictures as $picture) {
$pic = (string)$picture->xpath("pic:link/@extrabig")[0];
print_r($pic);
}
doesn't work.
Answer
Solution:
If you cast an element in xpath using string(), number() or boolean() it will cast the node value of that element. That means all text content inside that element and its descendants.
So if you use the expression
string(ad:ad-address)
it returns the content of both child nodes types:longitude and types:latitude. To get them separate you need to use separate expressions to fetch the longitude/latitude values.Output:
If you want to handle multiple elements you fetch a list first, iterate it and use expressions with a context node. The context node is the second argument of evaluate(). If you want attributes/content from the element you iterate you can use the just read them using getAttribute() or $nodeValue.
Output:
Answer
Solution:
The following code outputs the following. It was a rush job. I am sure you can refactor it and make it parse the feed dynamically.
Answer
Solution:
That's a hell of a XML...
Here is some code, using
simplexml
andxpath
. Sorry I'm not that much intoDOM
. This example requires PHP >= 5.4.You can access the other nodes according to these examples.
See it working: https://eval.in/97091
Comments:
(string)
= casting the xpath-results to string instead of getting objects as results...)[0];
= array dereferencing, requires PHP >= 5.4UPDATE: get the
@rel='extrabig'
@href
of the<pic:link>
nodes: