Reading xml with attributes in php - php

I have a xml. as shown in the attachment ..
How can I read the contents via php
http://agency.lastminute-hr.com/slike/xml_read1.jpg "XML"
Now I read this xml:
<?
$request = new SimpleXMLElement('<HotelInfoRequest/>');
$request->Username = 'SERUNCD';
$request->Password = 'TA78UNC';
$request->HotelID = '123';
$url = "http://wl.filos.com.gr/services/WebService.asmx/HotelInfo";
$result = simplexml_load_file($url . "?xml=" . urlencode($request->asXML()));
function RecurseXML($xml,$parent="")
{
$child_count = 0;
foreach($xml as $key=>$value)
{
$child_count++;
if(RecurseXML($value,$parent.".".$key) == 0) // no childern, aka "leaf node"
{
print($parent . "." . (string)$key . " = " . (string)$value . "<BR>\n");
}
}
return $child_count;
}
RecurseXML($result);
?>
this result look:
..
..
.Response.Hotels.Hotel.Rooms.Room.Quantity = 0
.Response.Hotels.Hotel.Rooms.Room.MaxPax = 3
.Response.Hotels.Hotel.Rooms.Room.MinPax = 2
.Response.Hotels.Hotel.Rooms.Room.RoomType.languages.lang = Room Double Standard
.Response.Hotels.Hotel.Rooms.Room.RoomType.languages.lang = Camera single standard
...
...
I need you to display the value and adttribut
<Rooms>
<Room ID = "5556">
<Quantity> 0 </ Quantity>
<MaxPax> 3 </ MaxPax>
<MinPax> 2 </ MinPax>
<Roomtype> </ roomtype>
</ Room>
....
..

Try (the first part is only for testing):
$string = <<<XML
<?xml version='1.0'?>
<Rooms>
<Room ID = "5556">
<Quantity> 0 </Quantity>
<MaxPax> 3 </MaxPax>
<MinPax> 2 </MinPax>
<Roomtype> </Roomtype>
</Room>
</Rooms>
XML;
$result = simplexml_load_string($string);
function RecurseXML($xml,$parent=".Response.Hotels.Hotel.Rooms"){
$children = $xml->children();
if ( empty($children) ) {
print($parent . "." . $xml->nodeName . " = " . (string)$xml . "<BR>\n");
}
else {
foreach($children as $key=>$value) {
RecurseXML($value, $parent . "." . $key);
}
}
}
RecurseXML($result);

Related

How to get all values from multiple XML child element for one parent element

I have XML file from my supplier. I want to read data from that file. My read.php file contains:
$xml = simplexml_load_file('export.xml');
$result = $xml->xpath("//product");
$array= array();
foreach ($result as $product) {
$id = (string)$product->id;
$code = (string)$product->code;
$ean = (string)$product->combinations->combination->ean;
$quantity = (string)$product->combinations->combination->quantity;
print_r('ID:' .$id. ' CODE:' .$code. ' EAN: '.$ean.' - <b>'.$quantity.'</b> szt.<br />');
}
XML looks like
<product>
<id>684</id>
<code>113</code>
<combinations>
<combination>
<ean>111</ean>
<quantity>0</quantity>
</combination>
<combination>
<ean>222</ean>
<quantity>5</quantity>
</combination>
<combination>
<ean>333</ean>
<quantity>2</quantity>
</combination>
</combinations>
</product>
It work quite fine but throw's only first combination
ID:684 CODE:113 EAN: 111 - 0 szt.
but i want also other combinations of this ID
ID:684 CODE:113 EAN: 222 - 5 szt.
ID:684 CODE:113 EAN: 333 - 2 szt.
Where to find solution?
Simple add a foreach $product->combinations->combination.
For Example:
$xml = simplexml_load_file('export.xml');
$result = $xml->xpath("//product");
$array= array();
foreach ($result as $product) {
$id = (string)$product->id;
$code = (string)$product->code;
foreach( $product->combinations->combination as $combination ){
$ean = (string)$combination->ean;
$quantity = (string)$combination->quantity;
print 'ID:' .$id. ' CODE:' .$code. ' EAN: '.$ean.' - <b>'.$quantity.'</b> szt.<br />';
}
}

ajax search box with xml database

I am trying to create a live search box on my website. I have an XML-file for a database. I've got the JavaScript part done, but I am a newbie at PHP and have some issues with this code I found on w3schools. My question is how do I modify the following code so that I only get the value of the "name" tag?
PHP code:
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load("links.xml");
$x=$xmlDoc->getElementsByTagName('link');
//get the q parameter from URL
$q=$_GET["q"];
//lookup all links from the xml file if length of q>0
if (strlen($q) > 0)
{
$hint="";
for($i=0; $i<($x->length); $i++)
{
$y=$x->item($i)->getElementsByTagName('title');
$z=$x->item($i)->getElementsByTagName('url');
if ($y->item(0)->nodeType==1)
{
//find a link matching the search text
if (stristr($y->item(0)->childNodes->item(0)->nodeValue,$q))
{
if ($hint=="")
{
$hint="<a href='" .
$z->item(0)->childNodes->item(0)->nodeValue .
"' target='_blank'>" .
$y->item(0)->childNodes->item(0)->nodeValue . "</a>";
}
else
{
$hint=$hint . "<br /><a href='" .
$z->item(0)->childNodes->item(0)->nodeValue .
"' target='_blank'>" .
$y->item(0)->childNodes->item(0)->nodeValue . "</a>";
}
}
}
}
}
// Set output to "no suggestion" if no hint were found
// or to the correct values
if ($hint == "")
{
$response="no suggestion";
}
else
{
$response=$hint;
}
//output the response
echo $response;
?>
XML:
<books>
<book>
<name>Harry Potter</name>
<quantity> 50 </quantity>
<price>19.90</price>
</book>
<book>
<name>Casino Royale</name>
<quantity> 50 </quantity>
<price>12.99</price>
</book>
<book>
<name>The Great Gatsby</name>
<quantity> 40 </quantity>
<price>14.90</price>
</book>
</books>
Thank you in advance for your answers! I really appreciate your help!
Here is an example of how you would do it:
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load("links.xml");
$books = $xmlDoc->getElementsByTagName("book");
//get the q parameter from URL
$q = $_GET["q"];
//lookup all links from the xml file if length of q>0
if (strlen($q) > 0) {
$hint = "";
foreach ($books as $book) {
$name = $book->getElementsByTagName("name")->item(0)->nodeValue;
$price = $book->getElementsByTagName("price")->item(0)->nodeValue;
$quantity = $book->getElementsByTagName("quantity")->item(0)->nodeValue;
echo "$name - $price - $quantity<br/>";
}
}
That will print out the $name, $price, and $quantity from the xml file for each book.

PHP XMLReader xml:lang

How can I read the xml:lang Value from this xml File???
<Catalog><Products>
<Product>
<Id>123</Id>
<Name xml:lang="en">name english product</Name>
<Description xml:lang="en">desc xyz</Description>
<Name xml:lang="de">name german</Name>
<Description xml:lang="de">desc germa</Description>
<Image num="1"><Url>pic.jpg</Url></Image>
<Image num="2"><Url>pic2.jpg</Url></Image>
</Product>
<Product>...
I want the value of the xml:lang="de" - Tag and the Image-Values.
Does anybody have an idea???
Thanx :-)
Update: I parse the xml like this, but how do i get this values???
$datei = "test.xml";
$z = new XMLReader;
$z->open($datei);
$doc = new DOMDocument;
while ($z->read() && $z->name !== 'Product');
$i = 0; while ($z->name === 'Product')
{ $i++;
$node = simplexml_import_dom($doc->importNode($z->expand(), true));
...
I think this should do it.
$simpleXml = new SimpleXMLElement(file_get_contents($datei));
foreach ($simpleXml->Products->Product as $product) {
$name = $product->xpath('Name[#xml:lang="en"]')[0];
echo $name . "\n";
foreach($product->Image as $img) {
echo $img->Url . "\n";
}
}
xpath use to many resurses. You can scan it, taking needed nodes. In the code you will see how take name and value of nodes and attributes, which have prefix.
$simpleXml = new SimpleXMLElement(file_get_contents($datei)));
foreach ($simpleXml->Products->Product as $products) // list of nodes with same name
foreach($products as $product) { // every node
if ($product->getName() === 'Image') { // for image take child
echo $product->Url->getName() . " = " . $product->Url ."\n";
$attrs = $product->attributes(); // Attribute without prefix
if(isset($attrs['num'])) echo " num = " . $attrs['num'] . "\n";
}
else echo $product->getName() . " = " . $product ."\n";
$attrs = $product->attributes('xml', true); // if 2nd true, 1st is prefix
if(isset($attrs['lang'])) echo " lang = " . $attrs['lang'] . "\n";
}
result
Id = 123
Name = name english product
lang = en
Description = desc xyz
lang = en
Name = name german
lang = de
Description = desc germa
lang = de
Url = pic.jpg
num = 1
Url = pic2.jpg
num = 2

Using XPath to select through namespaces

I've been trying to use XPath in PHP to access an Atom feed from the National Health Service API.
The data looks like this:
<feed xmlns:s="http://syndication.nhschoices.nhs.uk/services" xmlns="http://www.w3.org/2005/Atom">
<title type="text">NHS Choices - GP Practices Near Postcode - W1T4LB - Within 5km</title>
<entry>
<id>http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/27369</id>
<title type="text">Fitzrovia Medical Centre</title>
<updated>2011-08-20T22:47:39Z</updated>
<link rel="self" title="Fitzrovia Medical Centre" href="http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/27369?apikey="/>
<link rel="alternate" title="Fitzrovia Medical Centre" href="http://www.nhs.uk/ServiceDirectories/Pages/GP.aspx?pid=303A92EF-EC8D-496B-B9CD-E6D836D13BA2"/>
<content type="application/xml">
<s:organisationSummary>
<s:name>Fitzrovia Medical Centre</s:name>
<s:address>
<s:addressLine>31 Fitzroy Square</s:addressLine>
<s:addressLine>London</s:addressLine>
<s:postcode>W1T6EU</s:postcode>
</s:address>
<s:contact type="General">
<s:telephone>020 7387 5798</s:telephone>
</s:contact>
<s:geographicCoordinates>
<s:northing>182000</s:northing>
<s:easting>529000</s:easting>
<s:longitude>-0.140267259415255</s:longitude>
<s:latitude>51.5224357586293</s:latitude>
</s:geographicCoordinates>
<s:Distance>0.360555127546399</s:Distance>
</s:organisationSummary>
</content>
</entry>
</feed>
I'm now using this code to access the node.
<?php
$feedURL = 'http://v1.syndication.nhschoices.nhs.uk/organisations/pharmacies/postcode/W1T4LB.xml?apikey=&range=5';
$xml = file_get_contents($feedURL);
$sxml = new SimpleXMLElement($xml);
$sxml->registerXPathNamespace('a', 'http://www.w3.org/2005/Atom');
$sxml->registerXPathNamespace('s', 'http://syndication.nhschoices.nhs.uk/services');
$addr = $sxml->xpath('//s:address');
var_dump($addr[0]);
?>
Here $addr is empty but it should have ten entries.
Please can someone explain a good way to print out each <s:addressLine> node contents, and to place the postcode into a var.
I am working with the namespace principle in practice, although this is fairly new to me. Appreciate any information you could convey about learning XPath, and the PHP SimpleXML model.
Appreciate the help.
EDIT -
In seeing the update given below I decided to put my final output code into this:
function doPharmacy($postcode, $request, $prev, $next)
{
$feedURL = 'http://v1.syndication.nhschoices.nhs.uk/organisations/pharmacies/postcode/' . $postcode . '.xml?apikey=&range=5';
$xml = file_get_contents($feedURL);
$sxml = new SimpleXMLElement($xml);
$sxml->registerXPathNamespace('a', 'http://www.w3.org/2005/Atom');
$sxml->registerXPathNamespace('s', 'http://syndication.nhschoices.nhs.uk/services');
////////////// XPATH \\\\\\\\\\\\\\
$addrLines = $sxml->xpath('/a:feed/a:entry[' . $request . ']/a:content/s:organisationSummary/s:address/s:addressLine');
$nhsPostcode = $sxml->xpath('/a:feed/a:entry[' . $request . ']/a:content/s:organisationSummary/s:address/s:postcode');
$tel = $sxml->xpath('/a:feed/a:entry[' . $request . ']/a:content/s:organisationSummary/s:contact/s:telephone');
$distance = $sxml->xpath('/a:feed/a:entry[' . $request . ']/a:content/s:organisationSummary/s:Distance');
$title = $sxml->xpath('/a:feed/a:entry[' . $request . ']/a:title');
$link = $sxml->xpath('/a:feed/a:entry[' . $request . ']/a:link[#rel="alternate"]/#href');
$nhsPostcode = array_pop($nhsPostcode); // always taking first node from set
$tel = array_pop($tel);
$distance = (double)array_pop($distance);
$title = array_pop($title);
$link = array_pop($link);
////////////// OUTPUT: JSON \\\\\\\\\\\\\\
print '{"addr": "';
foreach ($addrLines as $addr)
{
print $addr . '<br />'; // ok to use HTML tags in JSON
}
print '",';
print '"postcode": "' . $nhsPostcode . '",';
print '"tel": "' . $tel . '",';
$num = number_format($distance, 2);
print '"distance": "' . $num . '",';
print '"title": "' . $title . '",';
print '"link": "' . $link . '",';
$nhsPostcode = urlencode($nhsPostcode);
print'"mapsURL": "http://maps.googleapis.com/maps/api/staticmap?center=' . $nhsPostcode . '&zoom=15&size=155x137&sensor=false&scale=2",';
print '"prev": "' . $prev . '",';
print '"next": "' . $next . '"';
print '}';
}
?>
This works for me:
$addr = $sxml->xpath('//s:address');
foreach ($addr as $a) {
$addressLine = $a->xpath('s:addressLine');
foreach ($addressLine as $al) {
echo (string)$al."<br/>";
}
$postalCode = $a->xpath('s:postcode');
foreach ($postalCode as $p) {
echo (string)$p."<br/>";
}
}
Which displays:
31 Fitzroy Square
London
W1T6EU
Previous answers have helped me a lot! So here go the complete solution.
$feedURL = "http://v1.syndication.nhschoices.nhs.uk/organisations/pharmacies/postcode/{$user->postcode}.xml?apikey=XXXX&range=100";
$xml = simplexml_load_file($feedURL);
$xml->registerXPathNamespace('s', 'http://syndication.nhschoices.nhs.uk/services');
$org = $xml->xpath('//s:organisationSummary');
$i = 0;
$item = array();
foreach ($org as $o)
{
$aux = $o->xpath('s:name');
$item[$i]['name'] = (string) $aux[0];
$addr = $o->xpath('s:address');
foreach ($addr as $a)
{
$aux = '';
$addressLine = $a->xpath('s:addressLine');
foreach ($addressLine as $a2)
{
$aux .= (string) $a2[0] . "\n";
}
$aux2 = $a->xpath('s:postcode');
if (is_array($aux2))
{
$aux .= (string) $aux2[0];
}
$item[$i]['address'] = $aux;
}
$i ++;
}
This will provide:
array (
0 =>
array (
'name' => 'Your Local Boots Pharmacy',
'address' => 'Century House
Station Road
Manningtree
CO11 1AA',
),
1 =>
array (
'name' => 'The Pharmacy',
'address' => 'The Street
East Bergholt
CO7 6SE',
), and so on...

how i can use SAX parser

This is what the result should look like when i parse it through a SAX parser
http://img13.imageshack.us/img13/6950/75914446.jpg
This is the XML source code from which i need to generate the display:
<orders>
<order>
<count>37</count>
<price>49.99</price>
<book>
<isbn>0130897930</isbn>
<title>Core Web Programming Second Edition</title>
<authors>
<count>2</count>
<author>Marty Hall</author>
<author>Larry Brown</author>
</authors>
</book>
</order>
<order>
<count>1</count>
<price>9.95</price>
<yacht>
<manufacturer>Luxury Yachts, Inc.</manufacturer>
<model>M-1</model>
<standardFeatures oars="plastic" lifeVests="none">false</standardFeatures>
</yacht>
</order>
<order>
<count>3</count>
<price>22.22</price>
<book>
<isbn>B000059Z4H</isbn>
<title>Harry Potter and the Order of the Phoenix</title>
<authors>
<count>1</count>
<author>J.K. Rowling</author>
</authors>
</book>
</order>
i really have no clue how to code the functions but i have just set up the parser
$xmlParser = xml_parser_create("UTF-8");
xml_parser_set_option($xmlParser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($xmlParser, 'startElement', 'endElement');
xml_set_character_data_handler($xmlParser, 'HandleCharacterData');
$fileName = 'orders.xml';
if (!($fp = fopen($fileName, 'r'))){
die('Cannot open the XML file: ' . $fileName);
}
while ($data = fread($fp, 4096)){
$parsedOkay = xml_parse($xmlParser, $data, feof($fp));
if (!$parsedOkay){
print ("There was an error or the parser was finished.");
break;
}
}
xml_parser_free($xmlParser);
function startElement($xmlParser, $name, $attribs)
{
}
function endElement($parser, $name)
{
}
function HandleCharacterData($parser, $data)
{
}
A SimpleXML-based recursive approach might be a simpler solution perhaps, something like:
$xml = new SimpleXmlElement($data);
function renderTree(SimpleXmlElement $xml, $depth = 0) {
$output = str_repeat('| ', $depth);
$output .= '+-' . $xml->getName();
if (sizeof($xml->attributes()) > 0) {
$attrs = '';
foreach ($xml->attributes() as $key => $value) {
$attrs .= $key . '=' . $value . ', ';
}
$output .= ' (' . trim($attrs, ', ') . ')';
}
$output .= ': ' . (string)$xml;
$output .= '<br />';
if ($xml->count() > 0) {
foreach ($xml->children() as $child) {
$output .= renderTree($child, $depth + 1);
}
}
return $output;
}
echo renderTree($xml);
Would render the tree as in the example image.

Categories