SimpleXML, возвращающий несколько объектов, как я могу получить данные? - PullRequest
2 голосов
/ 06 февраля 2010

Я использую 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.

Ответы [ 4 ]

7 голосов
/ 06 февраля 2010

Вы столкнулись с проблемой пространств имен и 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 :: children () . Он позволяет вам указать пространство имен дочерних элементов, которые вы хотите получить.

Например,

$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-скрипт может выяснить, что делать с данными.

2 голосов
/ 06 февраля 2010
$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 />';
}
1 голос
/ 06 февраля 2010

Попробуйте $sxml->entry[4]->thumb или что-то на этот счет.

AKA, чтобы получить доступ к первому идентификатору записи, вы должны пойти $sxml->entry[4]->id

В основном $sxml->entry - это массив SimpleXMLElement Object с. Когда вы читаете их, вы проходите через каждый объект и присваиваете ему $entry, так что $entry = $sxml->entry[0] и выше.

Вы можете пойти так:

print_r($sxml);

чтобы увидеть ВСЮ структуру. И это скажет вам, что вам нужно использовать для доступа к нему.

0 голосов
/ 07 февраля 2010

В итоге я сделал два цикла foreach, один из которых проходил через XML-ленту, показывающую самую последнюю запись одну . Затем я повторил объект вокруг этого, чтобы воспроизвести видео.

В другом я просмотрел последние четыре записи, возвращая элементы списка для списка миниатюр.

Теперь, когда я нажимаю на миниатюру видео, javascript обрабатывает передачу параметров в основную запись. Теперь, как перезагрузить этот главный объект после получения параметров, я открыт для идей.

...