How do I parse an individual entry from XML using PHP? - php

I am trying to parse an individual element from an XML string using PHP. The issue is that this individual element occurs before the entries start. The XML is below:
<?xml version="1.0" encoding="UTF-8"?>
<feed gd:kind="shopping#products" gd:etag=""lm_25heFT8yiumci9EH1kItJBpg/Sj5O9aXZ82PKpx3N2C3uQYMhNYE"" xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:s="http://www.google.com/shopping/api/schemas/2010">
<openSearch:totalResults>64</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>25</openSearch:itemsPerPage>
<entry >...</entry>
<entry >...</entry>
</feed>
I am trying to parse out the "64" in the opensearch:totalResults tag. How do I this and assign it to a variable in php? I tried:
$url = 'url of xml feed';
$xml = simplexml_load_file($url);
$entries =$xml->entry[0]->openSearch:totalResults;
// also tried $entries =$xml->openSearch:totalResults;
echo $entries;
but it's not working. Any advice?

You need to register namespace in order to access these nodes:
$xml = simplexml_load_file('file.xml');
$xml->registerXPathNamespace('os', 'http://a9.com/-/spec/opensearchrss/1.0/');
$nodes = $xml->xpath('os:totalResults');
$totalResults = (string)$nodes[0];

You can also use http://it1.php.net/manual/en/simplexmlelement.children.php (using the $ns parameter)
that is less resource intensive.

Related

PHP get specific data from xml file

This is XML file.
<?xml version="1.0" encoding="utf-8"?>
<UW xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<UWdata>
<List>
<IdProduct>1</IdProduct>
<ProductName>product</ProductName>
<ProductNameDE>product</ProductNameDE>
<ProductNameEN>product</ProductNameEN>
<Uf>1</Uf>
<PSIg>1</PSIg>
<Ug>1</Ug>
</List>
</UWdata>
</UW>
$lines_array=file($url);
$lines_string=implode('',$lines_array);
$xml=simplexml_load_string($lines_string) or die("Error: Cannot create object");
I try with this
echo $xml->UWdata[1]->ProductName;
But it doesn't return anything.I want to return Product name.
Sample code, Use simplexml_load_string
<?php
$a = '<?xml version="1.0" encoding="utf-8"?>
<UW xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<UWdata>
<List>
<IdProduct>1</IdProduct>
<ProductName>product</ProductName>
<ProductNameDE>product</ProductNameDE>
<ProductNameEN>product</ProductNameEN>
<Uf>1</Uf>
<PSIg>1</PSIg>
<Ug>1</Ug>
</List>
</UWdata>
</UW>';
$xml=simplexml_load_string($a) or die("Error: Cannot create object");
echo ($xml->UWdata->List->ProductName);
?>
When you load the xml file using the php simplexml_load_file function to a variable. The veritable becomes an object.
<?php
$xml=simplexml_load_file("/path/to/the/file.xml");
?>
So, in your case, the $xml variable becomes a multi-level object where every elements of xml file are key of the object. Like: UWdata.
So, as $xml is a multi-level object, to access the element under UWdata, under List under ProductName, you have to code like bellow.
echo $xml->UWdata->List->ProductName."<br>";
Here,
UWdata is the key of $xml object.
List is the key of UWdata.
ProductName is the key of List.
Finally, you will get the value of key element ProductName = product
I modified your script and put the xml in an external file called testxml.xml, as it should be. Always separate the function and the data it's supposed to handle. I used your xml like this:
<?xml version="1.0" encoding="utf-8"?>
<UW xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<UWdata>
<List>
<IdProduct>1</IdProduct>
<ProductName>productTEST</ProductName>
<ProductNameDE>product</ProductNameDE>
<ProductNameEN>product</ProductNameEN>
<Uf>1</Uf>
<PSIg>1</PSIg>
<Ug>1</Ug>
</List>
</UWdata>
</UW>
And with the following script it returns productTEST only.
$xmlstr = file_get_contents('./testxml.xml');
$xml = simplexml_load_string($xmlstr);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
echo $array['UWdata']['List']['ProductName'];
Hope this helps.
//edit:
While I do not know your project, you might want to take a foreach-approach if it is possible for your xml to contain more than one List element

Trouble figuring out how parsed xml is stored - simpleXML

Let's say my XML is like this:
<?xml version="1.0"?>
<lists>
<list
path=".">
<entry
kind="dir">
<name>Assignment1.1</name>
<commit
revision="1668">
<author>netid</author>
<date>2011-09-07T03:03:58.367692Z</date>
</commit>
</entry>
<entry
kind="file">
<name>Assignment1.1/.classpath</name>
<size>397</size>
<commit
revision="1558">
<author>netid</author>
<date>2011-09-06T17:00:52.998920Z</date>
</commit>
.
.
.
</list>
</lists>
And I store it in a SimpleXML object using
$xml_list = simplexml_load_file(dirname(__FILE__).'/svn_list.xml');
How would I access for example, the revision variable containing 1558?
I can't seem to figure it out using a combination of echo and print_r.
SimpleXML uses a set of classes which implement iterators to work through them, so you can loop through each node using foreach, however the easiest way to navigate the XML once it's loaded is by using SimpleXMLElement::xPath(). To get revision 1558, you can make the following call:
$commit = $xml_list->xpath('//list/entry/commit[#revision="1558"]');
This will return you the nodes underneath <commit revision="1558">, and you can then access them from the $commit variable, which extends ArrayObject.
To get the actual content of the <author> element, you must do the following:
print((string)$commit[0]->author);
SimpleXMLElement instances need to be cast to a type to expose their actual values.
Also, if you want to dump the content of $commit to see its child nodes, the easiest way is to call the asXml() method as follows:
print($commit[0]->asXml());
You are facing difficulties because you have error on your XML file , The </entry> tag was not closed.
You could traverse like this.
<?php
$xml='<lists>
<list>
<entry
kind="dir">
<name>Assignment1.1</name>
<commit
revision="1668">
<author>netid</author>
<date>2011-09-07T03:03:58.367692Z</date>
</commit>
</entry>
<entry
kind="file">
<name>Assignment1.1/.classpath</name>
<size>397</size>
<commit
revision="1558">
<author>netid</author>
<date>2011-09-06T17:00:52.998920Z</date>
</commit>
</entry>
</list>
</lists>';
$xml = simplexml_load_string($xml);
foreach ($xml->list->entry[0]->commit->attributes() as $a=>$v)
{
echo $v;
}
OUTPUT :
1668

easy xpath query but no results

Trying to get all URLs values from xml.
I have hundreds of entry exactly in the form like e.g. this entry 16:
<?xml version="1.0" encoding="utf-8" ?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<entries>
<entry id="16">
<revision number="1" status="accepted" wordclass="v" nounclasses="" unverified="false"></revision>
<media type="audio" url="http://website.com/file/65.mp3" />
</entry>
<entry id="17">
....
</entry>
</entries>
</root>
I am using this code but cannot get it to work. Why?
$doc = new DOMDocument;
$doc->Load('data.xml');
$xpath = new DOMXPath($doc);
$query = '//root/entries/entry/media';
$entries = $xpath->query($query);
What is the correc query for that? Best would be to only get the url value.
Your query probably returns the proper elements, but by default gives you the content of the media tag ( which in your case are empty, since the tag is self-closing ).
To get the url attribute of the tag you should use getAttribute(), example :
$entries = $xpath->query('//root/entries/entry/media');
foreach($entries as $entry) {
print $entry->getAttribute("url")."<br/>";
}
Or you should just xpath-query the attribute instead and read out it's value:
$urlAttributes = $xpath->query('//root/entries/entry/media/#url');
#####
foreach ($urlAttributes as $urlAttribute)
{
echo $urlAttribute->value, "<br/>\n";
#####
}
See DOMAttr::$valueDocs:
value
The value of the attribute
I would do that with SimpleXML actually:
$file = 'data.xml';
$xpath = '//root/entries/entry/media/#url';
$xml = simplexml_load_file($file);
$urls = array();
if ($xml) {
$urls = array_map('strval', $xml->xpath($xpath));
}
Which will give you all URLs as strings inside the $urls array. If there was an error loading the XML file, the array is empty.

Get XML values using PHP

I have a XML file. Here is a small version of that.
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
<title>Liste des ebooks</title>
<updated>2012-03-01T01:23:24Z</updated>
<author>
<name>Drown Del</name>
</author>
<opensearch:totalResults>2338</opensearch:totalResults>
<opensearch:itemsPerPage>100</opensearch:itemsPerPage>
<entry>
<category term="Romans" label="Romans"/>
<category term="Aventures" label="Aventures"/>
</entry>
</feed>
First I would like to know how do we call something like opensearch:totalResults in XML terms.
And I need your help with obtaining following values with PHP.
<opensearch:totalResults>2338</opensearch:totalResults> I need to get 2338 to a PHP variable.
Thank you.
Thank you all for your answers.
I could fix it with following way.
$xml = simplexml_load_string($xmltext);
$val = $xml->xpath('opensearch:totalResults');
echo $val[0];
parse all of this information into PHP using DOM. Ex.
$doc = new DOMDocument;
$doc->loadXML($xml); //$xml is your xml string
echo $doc->getElementsByTagName("totalResults")->item(0)->nodeValue;
For your first question, opensearch:totalResults is the qualified name of a start tag. It is called a qualified name (you might come across this as QName) because it contains the namespace (opensearch) for the tag.
For your second question, you can easily parse your XML into a DOMDocument and then query it for the value of the relevant tag. There are lots of examples on SO and of course on Google; a basic one from PHP.net is here.
Important note: Your current XML document does not contain an XML namespace declaration for the opensearch namespace, and will not parse as a result. You need to add such a declaration by making a modification:
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr"
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
If you need more powerful querying you can also use XPath. A minimal example would look like:
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('//opensearch:totalResults');
foreach ($nodes as $node) {
echo $node->nodeValue;
}
opensearch is a namespace, so you can try to access it like:
$yourXml->children('openSearch', true)->totalResults
Hope it helps
Check this out the exact result in PHP
<?php
$xml ='<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
<title>Liste des ebooks</title>
<updated>2012-03-01T01:23:24Z</updated>
<author>
<name>Drown Del</name>
</author>
<opensearch:totalResults>2338</opensearch:totalResults>
<opensearch:itemsPerPage>100</opensearch:itemsPerPage>
<entry>
<category term="Romans" label="Romans"/>
<category term="Aventures" label="Aventures"/>
</entry>
</feed>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$xmlD = simplexml_import_dom($dom);
echo $xmlD->totalResults;
?>
Read your xml file with simplexml_load_file as an object
Then get your variable like this:
$object->{'opensearch:totalResults'};

How to extract the content of <uri></uri> in a XML document?

I have a document that it's structure is like below.
There are a lot of <entry>. My question is how can I output the <uri> of each entry? And another question, how can I output only the USERNAME?
This is the file I want to get the usernames http://search.twitter.com/search.atom?q=yankees
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:google="http://base.google.com/ns/1.0" xml:lang="en-US" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://www.w3.org/2005/Atom" xmlns:twitter="http://api.twitter.com/" xmlns:georss="http://www.georss.org/georss">
<entry>
<author>
<name></name>
<uri>http://twitter.com/USERNAME</uri>
</author>
</entry>
<?php
$xml = new DOMDocument;
// link to ur file
$xml->load('');
foreach ($xml->getElementsByTagName('entry') as $product )
{
$append = array();
foreach($product->getElementsByTagName('uri') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
}
$result = $xml->saveXML();
print_r(str_replace('http://twitter.com/','',$result));
?>
You can use Xpath queries
http://www.php.net/manual/en/simplexmlelement.xpath.php
or
http://php.net/manual/en/domxpath.query.php
You should use SimpleXML some kind of a loop which goes trough all the s.
(foreach($xml->entry as $entry) loop should work fine, I think.)
And for the second: if it is always http://twitter.com/USERNAME, simply count the prefix's length than use a substr.
Resources to use: substr, SimpleXML, SimpleXML

Categories