0

I want to get 'url' attribute from 'media:content' tag of a RSS using simplexml. I searched the net for hours but cannot get it to work. This is the code:

<?php
$rss ='<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <item>
            <media:content url="http://blog.com/image1.jpg" width="661" height="310"/>
        </item>
    </channel>
</rss>';

$xml = simplexml_load_string($rss);
$url = $xml->children('media', true)->content;

var_dump($xml);
var_dump($url); // <- This is object(SimpleXMLElement)[3]
var_dump($url['url']); // <- This is NULL

The $url is NULL. ->content returns a SimpleXMLElement but it hasn't any url attribute!

rostamiani
  • 2,859
  • 7
  • 38
  • 74

3 Answers3

2

Firstly you have to make sure that your fetching the right content element, so make sure that you fetch the full path of the content node (note the extra path in setting up the $url variable). Then there are some oddities of fetching the attributes of a namespaced element (I believe they do not have a namespace themselves), to access them you have to use the attributes() method and then fetch the element using ['url']. You can try the added options...

$xml = simplexml_load_string($rss);
$url = $xml->channel->item->children('media', true)->content;

var_dump($xml);
var_dump($url); // <- This is object(SimpleXMLElement)[3]
var_dump($url['url']); // <- This is NULL
var_dump($url->attributes()['url']);
echo "url-".(string)$url->attributes()['url'].PHP_EOL;

The last two lines give you...

class SimpleXMLElement#6 (1) {
  public ${0} =>
  string(26) "http://blog.com/image1.jpg"
}
url-http://blog.com/image1.jpg

(echo will cast the value to a string anyway, but I put this in just in case you try assigning the value and wanted the value rather than the SimpleXMLElement object)

Nigel Ren
  • 56,122
  • 11
  • 43
  • 55
  • Thanks. This is a solution too. – rostamiani Feb 17 '18 at 02:20
  • Yes, [unprefixed attributes are always in no namespace at all](https://stackoverflow.com/questions/10672635/xml-namespaces-and-unprefixed-attributes). As a matter of style, you can also write `$url->attributes()->url`, and you can use `->attributes(null)` if you want to be explicit about "I'm selecting the null-namespace here". – IMSoP Feb 20 '18 at 12:43
1

You could use SimpleXMLElement xpath with for example this expression to get the media:content element:

/rss/channel/item/media:content

$xml = simplexml_load_string($rss);
$urls = $xml->xpath('/rss/channel/item/media:content');

// Get url from the first match
echo $urls[0]->attributes()->url;

// Loop all the matches
foreach ($urls as $url) {
    echo $url->attributes()->url;
}

Php demo output

Or you can loop though the children for this item:

foreach ($xml->channel->item->children("media", true) as $child) {
    echo $child->attributes()->url;
}

Php demo output

The fourth bird
  • 154,723
  • 16
  • 55
  • 70
0

The problem is that you are ignoring the media namespace.

In this link you can find more about how to address tags with a namespace specified.

In the example the namespace is passed to the children member function to scope the media:content tag.

$xml = simplexml_load_string($rss);
$url = $xml->children('http://search.yahoo.com/mrss/')->content;

var_dump($xml);
var_dump($url); // <- This is object(SimpleXMLElement)[3]
var_dump($url['url']); // <- This is NULL
Juan
  • 5,525
  • 2
  • 15
  • 26
  • children('media', TRUE) is identical to what you wrote. See this link: https://www.w3schools.com/php/func_simplexml_children.asp – rostamiani Feb 16 '18 at 03:11