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
Related
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 />';
}
}
here's the XML which I'm trying to parse for a while but I'm stuck on nested elements.
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:course="https://www.example.org/api/course/elements/1.0/" xmlns:staff="https://www.example.org/api/staff/elements/1.0/" version="2.0">
<channel>
<item>
<title>example.org course feed</title>
<link>https://www.example.org/api/v2/report/course-feed/rss</link>
<description>.org - course catalog feed</description>
<language>en</language>
<course:instructors>
<course:staff>
<staff:name>Mark Moran</staff:name>
</course:staff>
</course:instructors>
</item>
</channel>
how to parse course: instructors, my PHP code is
$rss = simplexml_load_file('https://www.edx.org/api/v2/report/course-feed/rss');
$namespaces = $rss->getNamespaces(true);
foreach ($rss->channel->item as $item) {
$title = $item->title ;
}
EDIT:2
$rss = simplexml_load_file('https://www.example.org/api/v2/report/course-feed/rss');
$namespaces = $rss->getNamespaces(true);//Add this line
foreach ($rss->channel->item as $item) {
$course_title = $item->title ;
$course_description = $item->description;
$course_url = $item->link;
$course = $item->children($namespaces['course']);
$course_thumbnail_url = $course->{'image-thumbnail'};
$course_banner_url = $course->{'image-banner'};
$course_teaser_url = $course->{'video-youtube'};
$course_start_date = $course->start;
$course_duration = $course->length;
$instructors = $item->children('course',true)->instructors;
$staff = $instructors->children('course',true)->staff;
$instructor_name = $staff->children('staff',true)->name;
$instructor_image = $staff->children('staff',true)->image;
echo $instructor_name.' '.$instructor_image,"<br>";
$course_price = 0;
$course_provider_id = 3;
$course_affiliates = $course->school;
$categories = $course->subject;
$categories = explode(',', $categories);
$c = count($categories);
$i = 0;
while($i < $c)
{
$course_rating = mt_rand(3.5,5);
$course_category = $categories[$i];
if(mysqli_query($conn,"INSERT into course_catalog_table (course_title,course_description,course_url,course_thumbnail_url,course_banner_url,course_teaser_url,course_category,course_start_date,course_duration,course_rating,course_affiliates,course_instructor,course_instructor_image,course_price,course_provider_id) VALUES('$course_title','$course_description','$course_url','$course_thumbnail_url','course_banner_url','course_teaser_url','$course_category','$course_start_date','$course_duration','$course_rating','$course_affiliates','$instructor_name',$instructor_image','$course_price')"))
{
echo "successfull\r\n";
}
$i++;
}
}
When i print instructor_name and instructor_image sometimes its prints but sometimes it throws warning that main(): Node no longer exists ,how can i check that is empty or not
You can use the children() function to access the child tree of the xml structure.
Do like this:
$rss->channel->item->children('course',true)->instructors;
Read: http://php.net/manual/en/simplexmlelement.children.php
But since the XML have multiple nest, you need to use multiple children() function to access the deepest nest.
Here is the modified code to parse the XML you give:
foreach ($rss->channel->item as $item)
{
$title = $item->title;
// access course:instructors nest
$instructors = $item->children('course',true)->instructors;
// then access the course:staff nest
$staff = $instructors->children('course',true)->staff;
// finally access the staff:name nest value
$name = $staff->children('staff',true)->name;
// print the value
echo "Staff Name: ". $name . "<br>";
}
Test run: https://eval.in/735810
I have Xml file like
<response>
<tag1>
<item>
<id>106</id>
<title>DG</title>
</item>
<item>
<id>105</id>
<title>AC</title>
</item>
</tag1>
<tag2>
<item>
<id>1</id>
<title>DjG</title>
</item>
<item>
<id>15</id>
<title>AoC</title>
</item>
</tag2>
</response>
I trying this code to extract ID and Title
$dom = new DomDocument();
$dom->load('xml.xml');
$xpath = new DOMXPath($dom);
foreach($xpath->evaluate('//response/*') as $node){
$params =$xpath->evaluate('//response/' .$node->nodeName . '/item/*');
foreach($params as $child) {
echo $node->nodeName ." = " .$child->nodeName ." = " .$child->nodeValue ."\n<br>";
}
}
But I get result such
<br>tag1 = id = 106
<br>tag1 = title = DG
<br>tag1 = id = 105
<br>tag1 = title = AC
<br>tag2 = id = 1
<br>tag2 = title = DjG
<br>tag2 = id = 15
<br>tag2 = title = AoC
But i need to get like this
tag1 = 106 = DG
tag1 = 105 = AC
tag2 = 1 = DjG
tag2 = 15 = AoC
On the second foreach, just target that $node->nodeName, then on the inner foreach target each id an title.
foreach($xpath->evaluate('//response/*') as $node) {
$tag = $node->nodeName;
$params = $xpath->evaluate("//$tag/*");
foreach($params as $child) {
$id = $xpath->evaluate('string(./id)', $child);
$title = $xpath->evaluate('string(./title)', $child);
echo $tag ." = " .$id ." = " .$title ."\n<br>";
}
}
Sample Output
Or the SimpleXML version:
$xml = simplexml_load_file('xml.xml');
foreach($xml as $tag =>$node) {
foreach($node as $item => $child) {
echo $tag ." = " .$child->id ." = " .$child->title ."\n<br>";
}
}
Sample Output
Use this code:
$dom = new DomDocument();
$dom->load('xml.xml');
$xpath = new DOMXPath($dom);
foreach($xpath->evaluate('//response/*') as $node){
$params =$xpath->evaluate('//response/' .$node->nodeName . '/*');
foreach($params as $child)
{
echo $node->nodeName ." = " .$child->getElementsByTagName('id')->item(0)->textContent ." = " .$child->getElementsByTagName('title')->item(0)->textContent ."\n<br>";
}
}
The second argument of DOMXpath::evaluate() is the context node. If you do not start the XPath expression with a slash, it will be relative to it. So inside a loop, you usually want to use the current node as the context for your expressions.
foreach ($xpath->evaluate('/absolute-expression') as $node) {
var_dump(
$xpath->evaluate('relative-expression', $node)
);
}
XPath (unlike CSS selectors) can fetch properties of the elements along different axes. You can get the local name (without namespace prefix) of a parent node with:
local-name(parent::*)
Using this, you can solve the problem with a single loop iterating the item elements.
Example:
$dom = new DomDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);
foreach ($xpath->evaluate('//response/*/item') as $node) {
echo
$xpath->evaluate('local-name(parent::*)', $node), ' = ',
$xpath->evaluate('string(id)', $node), ' = ',
$xpath->evaluate('string(title)', $node), "\n";
}
Output:
tag1 = 106 = DG
tag1 = 105 = AC
tag2 = 1 = DjG
tag2 = 15 = AoC
Only, If you need to call source for each first level node (tag1, tag2). You will need two loops. Like output the items grouped by the tag* element node.
$dom = new DomDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);
foreach ($xpath->evaluate('//response/*') as $node) {
echo
$xpath->evaluate('local-name()', $node),
"\n--------\n";
foreach ($xpath->evaluate('item', $node) as $item) {
echo
$xpath->evaluate('string(id)', $item), ' = ',
$xpath->evaluate('string(title)', $item), "\n";
}
echo "\n";
}
Output:
tag1
--------
106 = DG
105 = AC
tag2
--------
1 = DjG
15 = AoC
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);
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...