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 :(
}
答案 0 :(得分:7)
您在问题中获得的代码可以正常运行。您已经正确地写过,您可以通过使用带有XML命名空间相关参数$ns
的{{3}}来访问不在默认命名空间中的namespaced元素作为根元素的属性。 $is_prefix
:
$youtube->entry->children('yt', TRUE)->duration->attributes()->seconds; // is "1870"
由于这与您在问题中的基本相同,可以说您已经回答了自己的问题。与扩展的SimpleXMLElement::children()
method进行比较。
答案很长:您在问题中获得的代码确实有效。您可以在此处在线交互式示例中找到示例XML和代码:Online Demo #2 - 它显示不同PHP和LIBXML版本的结果。
代码:
$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";
结果:
输出为5.3.26,5.4.16 - 5.5.0
ibxml version: 2.9.1
1870
done. should read 1870 one time.
5.3.15 - 5.3.24,5.4.5 - 5.4.15的输出
ibxml version: 2.8.0
1870
done. should read 1870 one time.
5.1.2 - 5.3.14,5.4.0 - 5.4.4
的输出ibxml version: 2.7.8
1870
done. should read 1870 one time.
从这个角度看,一切都很好。由于您没有给出任何具体的错误描述,因此很难说您的案例出了什么问题。您可能正在使用在您提出问题时过时的PHP版本,例如收到致命错误:
致命错误:调用未定义的方法SimpleXMLElement :: getNameSpaces()
可能还有一个过时的libxml版本。根据测试,以下libxml版本适用于PHP 5.1.2-5.5.0:
答案 1 :(得分:2)
所以我找到了一种使用xpath的方法,这是最好的方法还是有一种方法与我的问题中的代码一致?只是出于好奇。
$source = 'youtube.xml';
// load as file
$youtube = new SimpleXMLElement($source, null, true);
$youtube->registerXPathNamespace('yt', 'http://gdata.youtube.com/schemas/2007');
$count = 0;
foreach($youtube->entry as $item){
//title works
echo $item->title;
$attributes = $item->xpath('//yt:duration/@seconds');
echo $attributes[$count]['seconds'];
$count++;
}
答案 2 :(得分:2)
我正在努力解决这种情况,然后我找到了解决方案。如何阅读复杂的XML属性命名空间非常简单。
foreach($media->group->content as $content) {
$attrs = $content->attributes();
$ytformat = $content->attributes("yt","format");
echo(" attr = " . $ytformat . "; ");
if ($ytformat == 5) {
$url = $attrs['url'];
$type = $attrs['type'];
echo ($url . " - " . $type);
}
}
希望它有帮助...:)
答案 3 :(得分:2)
以下是仅使用attributes()和children()的另一种解决方案,经过测试并正常工作! :)
$data=<<<XML
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<item>
<title>Title: 0</title>
<link test="test" test2="This is a test">Link:0</link>
<media:thumbnail url="Thumbnail URL: 0"/>
<media:content url="Content URL: 0" type="video/mp4" />
</item>
<item>
<title>Title: 1</title>
<link>Link:1</link>
<media:thumbnail url="1"/>
<media:content url="1" type="video/mp4" />
</item>
</channel>
</rss>
XML;
$xml=simplexml_load_string($data);
//reading simple node
echo $xml->channel[0]->item[0]->title;
echo "<br>----------------------------------<br>";
//reading/updating simple node's attribute
echo $xml->channel[0]->item[0]->link->attributes()->test2="This is a NEW test!.";
echo "<br>----------------------------------<br>";
//reading/updating namespaced node's attribute
echo $xml->channel[0]->item[0]->children('media',TRUE)->content->attributes()->type="VIDEO/MP6";
//saving...
$xml->asXml('updated.xml');