Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get attribute of node with namespace using SimpleXML? [closed]

youtube.xml

<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:gd="http://schemas.google.com/g/2005" xmlns:yt="http://gdata.youtube.com/schemas/2007">  

    <entry>
        ...
        <yt:duration seconds="1870"/>
        ...
    </entry>

</feed>

update_videos.php

$source = 'youtube.xml';

// load as file
$youtube = new SimpleXMLElement($source, null, true);

foreach($youtube->entry as $item){
    //title works
    echo $item->title;

    //now how to get seconds? My attempt...
    $namespaces = $item->getNameSpaces(true);
    $yt = $item->children($namespaces['yt']);
    $seconds = $yt->duration->attributes();
    echo $seconds['seconds'];
    //but doesn't work :(
}   
like image 370
Jonathan Avatar asked Jul 04 '11 23:07

Jonathan


1 Answers

The code you've got in your question does work. You have correctly written that you can access an attribute from a namespaced-element that is not in the default namespace as the root-element by making use of the SimpleXMLElement::children() method with the XML-namespace related parameters $ns and $is_prefix:

$youtube->entry->children('yt', TRUE)->duration->attributes()->seconds; // is "1870"

As this is basically the same as you did in your question, one could say that you have answered your own question. Compare with the extended Online Demo #2.


Long answer: The code you've got in your question does work. You can find your example XML and code in an interactive example online here: Online Demo #1 - it shows the result with different PHP and LIBXML versions.

Code:

$buffer = '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:yt="http://gdata.youtube.com/schemas/2007">
    <entry>
        <yt:duration seconds="1870"/>
    </entry>
</feed>';

$xml = new SimpleXMLElement($buffer);

echo "ibxml version: ", LIBXML_DOTTED_VERSION, "\n";

foreach ($xml->entry as $item)
{
    //original comment: how to get seconds?
    $namespaces = $item->getNameSpaces(true);
    $yt         = $item->children($namespaces['yt']);
    $seconds    = $yt->duration->attributes();

    echo $seconds['seconds'], "\n"; // original comment: but doesn't work.
}

echo "done. should read 1870 one time.\n";

Results:

Output for 5.3.26, 5.4.16 - 5.5.0

ibxml version: 2.9.1
1870
done. should read 1870 one time.

Output for 5.3.15 - 5.3.24, 5.4.5 - 5.4.15

ibxml version: 2.8.0
1870
done. should read 1870 one time.

Output for 5.1.2 - 5.3.14, 5.4.0 - 5.4.4

ibxml version: 2.7.8
1870
done. should read 1870 one time.

From this perspective everything looks fine. As you have not given any concrete error description it's hard to say what went wrong on your case. You were probably using a PHP version that was outdated the time you asked your question, for example getting a fatal error:

Fatal error: Call to undefined method SimpleXMLElement::getNameSpaces()

Probably also due to an outdated libxml version. According to the test, the following libxml versions work fine with PHP 5.1.2-5.5.0:

  • ibxml version: 2.9.1
  • ibxml version: 2.8.0
  • ibxml version: 2.7.8
like image 107
hakre Avatar answered Sep 28 '22 16:09

hakre