SimpleXML возвращает несколько объектов. Как мне получить данные?
-
18-09-2019 - |
Вопрос
Я использую simpleXML для анализа этот XML-файл.Это канал, который я использую для доступа к API YouTube.Я хочу встроить в объект самое последнее видео и отобразить следующие четыре миниатюры.
Поэтому я использую simplexml_load_file
по этому поводу, используя foreach
цикл для доступа к значениям в каждом канале.
Я могу без проблем получить доступ к значениям, но столкнулся с проблемой, заключающейся в том, что каждое видео хранится в отдельном SimpleXMLElement Object
.У меня нет никакого контроля над тем, к какому объекту я обращаюсь, поскольку они не хранятся в массиве.Поэтому я не могу получить, скажем, $thumb[4]
или $entry[4]->thumb
.
Я пытался использовать SimpleXMLIterator
, но по какой-то причине любые значения, имеющие одинаковое начало, отображаются как пустые.Например, видео может иметь одиннадцать вариантов:
И каждый из них будет отображаться как [1]=""
, [2]=""
, [3]=""
, и т. д.
Я с радостью предоставлю дополнительную информацию всем, кто сможет помочь!
Редактировать
Вот print_r моих результатов.Это сделано для одной переменной, чтобы дать вам представление о проблеме структуры, с которой я столкнулся.Весь print_r($entry) предоставит переменные для каждого узла в XML-файле.
SimpleXMLElement Object
(
[0] => 159
)
SimpleXMLElement Object
(
[0] => 44
)
Кроме того, print_r просто находится внутри блока PHP для тестирования.На самом деле я хочу получить доступ к переменным в эхо в HTML.
Решение
Вы столкнулись с проблемой пространства имен и SimpleXML.Лента начинается с
<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'>
А xmlns='http://www.w3.org/2005/Atom'
устанавливает пространство имен по умолчанию http://www.w3.org/2005/Atom
.Т.е.его дочерние элементы на самом деле не id
, updated
, category
но http://www.w3.org/2005/Atom:id
, http://www.w3.org/2005/Atom:updated
и так далее...
Таким образом, вы не можете получить доступ к элементу id через $feed->id
, вам нужен метод SimpleXMLELement::дети().Он позволяет вам указать пространство имен дочерних элементов, которые вы хотите получить.
Например,
$feed = simplexml_load_file('http://gdata.youtube.com/feeds/api/videos?author=ofcoursegolf&max-results=5&prettyprint=true');
$children = $feed->children('http://www.w3.org/2005/Atom');
echo $children->updated;
В настоящее время печатает 2010-02-06T05:23:33.858Z
.
Чтобы получить идентификатор первого элемента записи, вы можете использовать echo $children->entry[0]->id;
.
Но тогда ты попадешь в <media:group>
элемент и его дочерние элементы <media:category
, <media:player>
и так далее..., которые находятся в xmlns:media='http://search.yahoo.com/mrss/'
пространство имен.
$feed = simplexml_load_file('http://gdata.youtube.com/feeds/api/videos?author=ofcoursegolf&max-results=5&prettyprint=true');
$group = $feed->children('http://www.w3.org/2005/Atom')
->entry[0]
->children('http://search.yahoo.com/mrss/')
->group
->children('http://search.yahoo.com/mrss/')
;
echo $group->player->attributes()->url, "\n";
foreach( $group->thumbnail as $thumb) {
echo 'thumb: ', $thumb->attributes()->url, "\n";
}
(В настоящее время) печатает
http://www.youtube.com/watch?v=ikACkCpJ-js&feature=youtube_gdata
thumb: http://i.ytimg.com/vi/ikACkCpJ-js/2.jpg
thumb: http://i.ytimg.com/vi/ikACkCpJ-js/1.jpg
thumb: http://i.ytimg.com/vi/ikACkCpJ-js/3.jpg
thumb: http://i.ytimg.com/vi/ikACkCpJ-js/0.jpg
Редактировать:Я бы, вероятно, сделал это в браузере, используя гораздо больше JavaScript, но вот пример приложения (простой и некрасивый).
<?php
//define('TESTENV' , true);
function getFeed($author) {
// <-- add caching here if needed -->
if ( !defined('TESTENV') ) {
$url = sprintf('http://gdata.youtube.com/feeds/api/videos?author=%s&max-results=5',
urlencode($author)
);
}
else {
$url = 'feed.xml';
}
return simplexml_load_file($url);
}
$feed = getFeed('jonlajoie');
if ( !isset($_GET['id']) ) {
$selected = '';
}
else {
$selected = $_GET['id'];
printf ('
<object width="425" height="344">
<param name="movie" value="http://www.youtube.com/v/%s"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always">
</param>
<embed src="http://www.youtube.com/v/%s" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed>
</object>',
htmlspcialchars($selected), htmlspcialchars($selected)
);
}
$item = 0;
foreach( $feed->children('http://www.w3.org/2005/Atom')->entry as $entry ) {
$entryElements = $entry->children('http://www.w3.org/2005/Atom');
$groupElements = $entry
->children('http://search.yahoo.com/mrss/')
->group
->children('http://search.yahoo.com/mrss/')
;
if ( !preg_match('!^http://gdata.youtube.com/feeds/api/videos/([^/]+)!', $entryElements->id, $m) ) {
// google can choose whatever id they want. But this is only a simple example....
die('unexpected id: '.htmlspecialchars($entryElements->id));
}
$id = $m[1];
if ( $selected!==$id ) {
printf('<a href="?id=%s"><img src="%s" /></a>',
urlencode($id),
$groupElements->thumbnail[0]->attributes()->url
);
}
}
Редактировать 2:«И когда я нажимаю на миниатюры, я использую jQuery для загрузки видео в основное пространство.Похоже, мне понадобится точный доступ к узлу[#], верно?»
Если вы уже используете JavaScript/jQuery, ваш PHP-скрипт (если он вообще нужен) может просто вернуть массив (в кодировке JSON) всех данных для всего видео, и ваш jQuery-скрипт сможет выяснить, что делать с данными.
Другие советы
$doc = new DOMDocument();
$doc->loadXML(file_get_contents('http://gdata.youtube.com/feeds/api/videos?author=ofcoursegolf&max-results=5&prettyprint=true'));
$xpd = new DOMXPath($doc);
$xpd->registerNamespace('atom', "http://www.w3.org/2005/Atom");
false&&$node = new DOMElement();//this is for my IDE to have intellysense
$result = $xpd->query('//atom:feed/atom:entry[1]/media:group/media:thumbnail');
foreach($result as $node){
echo $node->getAttribute('url').'<br />';
}
echo "more results <br />";
$result = $xpd->query('//atom:feed/atom:entry[1]/media:group/media:thumbnail[1]');
foreach($result as $node){
echo $node->getAttribute('url').'<br />';
}
Пытаться $sxml->entry[4]->thumb
или что-то в этом отношении.
АКА, чтобы получить доступ к идентификатору первой записи, вы должны пойти $sxml->entry[4]->id
По сути $sxml->entry
представляет собой массив SimpleXMLElement Object
с.Когда вы их выполняете, вы просматриваете каждый объект и назначаете его $entry
, так что $entry = $sxml->entry[0]
и вверх.
Вы можете пойти следующим образом:
print_r($sxml);
чтобы увидеть ВСЮ структуру.И там будет указано, что вам нужно использовать для доступа к нему.
В конце концов я выполнил два цикла foreach, один из которых проходил через XML-фид, показывающий самые последние данные. один вход.Затем я воспроизвел объект вокруг этого, чтобы воспроизвести видео.
В другом я просматривал последние четыре записи, возвращая элементы списка для списка миниатюр.
Теперь, когда я нажимаю на миниатюру видео, JavaScript обрабатывает передачу параметров в основную запись.Теперь, как перезагрузить этот основной объект после получения параметров, я открыт для идей.