2

Given this XML structure:

$xml = '<rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
            <channel>
                <item>
                    <title>Title</title>
                    <media:group>
                        <media:content url="url1" />
                        <media:content url="url2" />
                    </media:group>
                </item>
                <item>
                    <title>Title2</title>
                    <media:group>
                        <media:content url="url1" />
                        <media:content url="url2" />
                    </media:group>
                </item>
            </channel>
        </rss>';
$xml_data = new SimpleXMLElement($xml);

How do I access the attributes of the media:content nodes? I tried

foreach ($xml_data->channel->item as $key => $data) {
    $urls = $data->children('media', true)->children('media', true);
    print_r($urls);
}

and

foreach ($xml_data->channel->item as $key => $data) {
    $ns = $xml->getNamespaces(true);
    $urls = $data->children('media', true)->children($ns['media']);
    print_r($urls);
}

as per other answers, but they both return empty SimpleXMLElements.

J. Doe
  • 25
  • 3
  • The first argument of `children()` is `$ns`. You have to set the namespace URL (`"http://search.yahoo.com/mrss/"`), but this URL seems to be not longer valid. See : https://stackoverflow.com/questions/11648401/how-to-get-mediacontent-with-simplexml#11649046 and https://stackoverflow.com/questions/35877048/how-to-parse-xmls-mediacontent-with-php – Syscall Feb 12 '18 at 14:13
  • @Syscall, you can use the prefix if you pass true as the second parameter. – Nigel Ren Feb 12 '18 at 14:30
  • @NigelRen Oh, Right! Thanks. – Syscall Feb 12 '18 at 14:34

1 Answers1

0

When you echo out XML with SimpleXML, you need to use asXML() to see the real content, print_r() does it's own version and doesn't show all the content...

foreach ($xml_data->channel->item as $key => $data) {
    $urls = $data->children('media', true)->children('media', true);
    echo $urls->asXML().PHP_EOL;
}

echos out...

<media:content url="url1"/>
<media:content url="url1"/>

It only outputs the first one of each group as you will need to add another foreach to go through all of the child nodes for each element.

foreach ($xml_data->channel->item as $key => $data) {
    echo $data->title.PHP_EOL;
    foreach ( $data->children('media', true)->children('media', true) as $content )   {
        echo $content->asXML().PHP_EOL;
    }
}

outputs..

Title
<media:content url="url1"/>
<media:content url="url2"/>
Title2
<media:content url="url1"/>
<media:content url="url2"/>

To access a particular attribute (so for example the url attribute from the second code example) you have to use the attributes() method...

echo $content->attributes()['url'];
Nigel Ren
  • 56,122
  • 11
  • 43
  • 55