PHP noob here. I seem to be misunderstanding how to get the value of an XML node using XPath, and I haven't been able to find a StackOverflow answer that quite address what I'm doing wrong.
So, using RPG Geek's API, I'm trying to pull some information about the game Dread. (Here's a link to the URI.)
$rpggeekXML = simplexml_load_file('https://www.rpggeek.com/xmlapi/boardgame/166952?&stats=1');
$rating = $rpggeekXML->xpath('ratings/average');
$usersrated = $rpggeekXML->xpath('ratings/usersrated');
I know I'm successfully pulling in the rpggeek XML because if I do var_dump($rpggeekXML);, I can see all of the information I'm expecting. However, if I do var_dump($rating); or var_dump($usersrated);, it returns array(0) { }. So it seems I must be screwing up the XPath lines, but I can't figure out how. What am I doing wrong?
Use full path to find desired node:
$rating = $rpggeekXML->xpath( 'boardgame/statistics/ratings/average' );
echo $rating[0];
Collect all "average" nodes in document:
$rating = $rpggeekXML->xpath( '//average' );
echo $rating[0];
I think you xpath syntax is wrong. You can try this
$rpggeekXML = simplexml_load_file('https://www.rpggeek.com/xmlapi/boardgame/166952?&stats=1');
$rating = $rpggeekXML->xpath('//ratings/average');
$usersrated = $rpggeekXML->xpath('//ratings/usersrated');
Related
Sorry to be asking this, but it's driving me crazy.
I've been using the php SimpleXMLElement as my XML go to parser, and I've looked at many examples, and have given up on this many times. But, now, I just need to have this working. There are many examples on how to get simple fields, but not so many with values in the fields...
I'm trying to get the "track_artist_name" value from this XML as a named variable in php.
<nowplaying-info-list>
<nowplaying-info >
<property name="track_title"><![CDATA[Song Title]]></property>
<property name="track_album_name"><![CDATA[Song Album]]></property>
<property name="track_artist_name"><![CDATA[Song Artist]]></property>
</nowplaying-info>
</nowplaying-info-list>
I've tried using xpath with:
$sxml->xpath("/nowplaying-info-list[0]/nowplaying-info/property[#name='track_artist_name']"));
But, I know it's all mucked up and not working.
I originally tried something like this too, thinking it made sense - but no:
attrs = $sxml->nowplaying_info[0]->property['#name']['track_artist_name'];
echo $attrs . "\n\n";
I know I can get the values with something such as this:
$sxml->nowplaying_info[0]->property[2];
Sometimes there are more lines in the XML results than other times, and so because of this, it is breaks the calculations with the wrong data.
Can someone shed some light on my problem? I'm just trying to the name of the artist to a variable. Many thanks.
*** WORKING UPDATE: **
I was unaware there were different XML interpreter methods, and was using the following XML interpreter version:
// read feed into SimpleXML object
$sxml = new SimpleXMLElement($json);
That didn't work, but have now updated to the following (for that section of code) thanks to the help here.
$sxml_new = simplexml_load_string($json_raw);
if ( $sxml_new->xpath("/nowplaying-info-list/nowplaying-info/property[#name='track_artist_name']") != null )
{
$results = $sxml_new->xpath("/nowplaying-info-list/nowplaying-info/property[#name='track_artist_name']");
//print_r($results);
$artist = (string) $results[0];
// var_dump($artist);
echo "Artist: " . $artist . "\n";
}
Your xpath expression is pretty much right, but you don't need to specify an index for the <nowplaying-info-list> element - it'll deal with that itself. If you were to supply an index, it would need to start at 1, not 0.
Try
$results = $sxml->xpath("/nowplaying-info-list/nowplaying-info/property[#name='track_artist_name']");
echo (string) $results[0];
Song Artist
See https://3v4l.org/eH4Dr
Your second approach:
$sxml->nowplaying_info[0]->property['#name']['track_artist_name'];
Would be trying to access the attribute named #name of the first property element, rather than treating it as an xpath-style # expression. To do this without using xpath, you'd need to loop over each of the <property> elements, and test their name attibrute.
Just in case if the node you are looking for is deeply residing some where, you could just add a double slash at the start.
$results = $sxml->xpath("//nowplaying-info-list/nowplaying-info/property[#name='track_artist_name']");
Also in case if you have multiple <nowplaying-info> elements. You could make of use of the index for that. (note the [1] index)
$results = $sxml->xpath("//nowplaying-info-list/nowplaying-info[1]/property[#name='track_artist_name']");
I am rather new to development, but a long time sys-admin. I am trying to retrieve a specific value from the following XML feed. (Its oBix).
http://80.68.58.47:900/obix/config/Drivers/NiagaraNetwork/OSS_Tridium_Demo/points/kW_Sys/
I am trying to return the "Out" value within the 'Real' element (If element is the right name for it). The value is a number next to val=.
I have spent a fair few hours trying to work out how to isolate the 'val' attribute and return the number but I can't seem to do it. I can isolate the 'real' element but can't go any further in to get the actual number value.
Could someone show me how this is done using PHP SimpleXML so I can try to get my head round it?
This is my code so far:
<?php
$url = "http://80.68.58.47:900/obix/config/Drivers/NiagaraNetwork/OSS_Tridium_Demo/points/kW_Sys/";
$xml = simplexml_load_file($url);
$elementselection = $xml->real[0];
$outputvalue = $elementselection;
print_r ($outputvalue);
?>
Many Thanks!
Tom
If you just want the value from the first 'real' element you can use the following:
$url = "http://80.68.58.47:900/obix/config/Drivers/NiagaraNetwork/OSS_Tridium_Demo/points/kW_Sys/";
$xml = simplexml_load_file($url);
$value = (string) $xml->real[0]['val'];
var_dump($value);
$file = simplexml_load_file($url); {
foreach($file->entry as $post) {
$row = simplexml_load_string($post->asXML()); // after adding this line, i get error message
$links = $row->xpath('//link[#rel="alternate" and #type="text/html"]');
echo (string) $post->title;
echo (string) $links[0]['href'];
I use this script to parse atom feed. At first didn't work because it couldn't pass the link's href attribute properly. I added $row and even though it worked, it gives an error : "namespace prefix gd for etag on entry is not defined". I'm searching this for hours, can't find a solution. I was so close.
The line $row = simplexml_load_string($post->asXML());, if it worked, would be a long-winded way of writing $row = $post. ->asXML() and simplexml_load_string perform the opposite action to each other so you'd get back the same object you started with.
I think the reason it's behaving strangely in your case is that your XML document is using "namespaces", and the fragment of XML produced by $post->asXML() doesn't quite work as an XML document on its own.
I suspect that the original problem you had, which this line seemed to magically fix, was also with namespaces, as XPath is rather sensitive to them. Look up examples of using registerXPathNamespace and see if they solve your problem. If not, feel free to post a follow-up question showing your original problem, and including a sample of the XML you're processing.
I'd like to parse google geocode api respond, but the structure of the result is not always the same. I need to know the postal code for example, but it is sometimes in the Locality/DependentLocality/PostalCode/PostalCodeNumber node and sometimes in the Locality/PostalCode/PostalCodeNumber node. I don't really know the logic behind this, just want to get the value of the PostalCodeNumber node, no matter where is it exactly. Can I do it with XPath? If so, how?
UPDATE
Tried with //PostalCodeNumber but it returns an empty array. The code snippet is the following:
$xml = new \SimpleXMLElement($response);
var_dump($xml->xpath('//PostalCodeNumber'));
The $response is the content of http://maps.google.com/maps/geo?q=1055+Budapest&output=xml
(copy paste the url instead of clicking on it because of some character problems...)
Try to use this XPath:
Locality//PostalCodeNumber
It will find all descendants PostalCodeNumber of Locality element.
//PostalCode/PostalCodeNumber
Should do the trick. A quick google search yields the following schema snippet, indicating that there may be multiple DependentLocality elements, nested, so you'll want to check for multiple results, and have some idea of whether you want the most specific (most deeply nested) or least specific.
Update:
To guard against namespace issues, explicitly add the namespace to the query:
$xml = new SimpleXMLElement($response);
$xpath->registerXPathNamespace('ns', 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0');
var_dump($xml->xpath('//ns:PostalCodeNumber'));
Update 2: fixed a couple of typos
Update 3:
<?php
$result = file_get_contents('http://maps.google.com/maps/geo?q=1055+Budapest&output=xml');
$sxe = new SimpleXMLElement($result);
$sxe->registerXPathNamespace('c', 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0');
$search = $sxe->xpath('//c:PostalCodeNumber');
foreach($search as $code) {
echo $code;
}
?>
I don't know if you are able to do this, but...
Is there anyway to get a part of the content from a URL ?
Like if I have this:
<protected>false</protected>
<followers_count>6</followers_count>
<profile_background_color>00afe0</profile_background_color>
(The whole content is from Twitter)
But only want the <followers_count>6</followers_count> part?
Somebody who know how to do this?
(I hope you guys know what I mean by this)
PS. Anything above is JUST an example
PSS. Not just gona use this for xml, etc this format too (Which I don't know the name of)
Yes, I know that I could just use the file_get_contents-offset and maxlen thing, but the problem is, that I don't always know, where the part I'm looking for is.
You could use a native XML parser such as SimpleXML to find the value of a specific piece of content.
What you're looking at is called XML. PHP has a built-in XML parser which will allow you to extract the data you need.
$xml = simplexml_load_file(
'http://twitter.com/users/show.xml?screen_name=SlogaNator'
);
$follower_count = (int) $xml->followers_count; // int(6)
$data = file_get_contents('http://twitter.com/users/show.xml?screen_name=SlogaNator');
$xml = simplexml_load_string($data);
echo $xml->followers_count; # 6
"Let's give this guy minuses because he doesn't know you shouldn't parse XML with RegExp" version...
preg_match('#<followers_count>([0-9]+)</followers_count>#is', $xml, $matches);
echo $matches[1]; # 6