【问题标题】:SimpleXML returning multiple objects, how can I get the data?SimpleXML 返回多个对象,我如何获取数据?
【发布时间】:2010-02-06 04:09:50
【问题描述】:

我正在使用 simpleXML 来解析 this xml file。这是我用来访问 YouTube API 的提要。我想在一个对象中嵌入最近的视频并显示接下来的四个缩略图。

所以我在此使用simplexml_load_file,并使用foreach 循环访问每个提要中的值。

我可以毫无问题地访问这些值,但我遇到了将每个视频存储在单独的SimpleXMLElement Object 中的问题。我无法控制要访问的对象,因为它们没有存储在数组中。所以我不能得到$thumb[4]$entry[4]->thumb

我尝试使用SimpleXMLIterator,但无论出于何种原因,任何具有相同开头的值都会呈现为空白。例如,视频可能有 11 种变体:

这些将分别呈现为[1]=""[2]=""[3]="" 等。

我很乐意为任何可以提供帮助的人提供更多信息!

编辑

这是我的结果的 print_r。这是在单个变量上完成的,让您了解我面临的结构问题。整个 print_r($entry) 将为 XML 文件中的每个节点提供变量。

SimpleXMLElement Object
(
    [0] => 159
)
SimpleXMLElement Object
(
    [0] => 44
)

另外,print_r 只是在 PHP 块中用于测试。我实际上是在寻找访问 HTML 中回声中的变量。

【问题讨论】:

  • 你能给我们一个print_rvar_dump的部分结构吗?不是全部,但足以让我们看到它的样子。
  • 当然,恰恰。添加。让我知道是否还有其他内容可以更清晰。
  • 包含哪些对象?
  • 没什么,那是变量的 print_r。也许我误解了你的问题。上下文(可能矫枉过正):这个 (droplr.com/lMQ70) 是 $entry 的 print_r,它是由这个 (droplr.com/lMR2X) PHP 提供的。

标签: php xml simplexml youtube-api


【解决方案1】:

您遇到了namespaces and 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。 IE。它的子元素实际上不是idupdatedcategory,而是http://www.w3.org/2005/Atom:idhttp://www.w3.org/2005/Atom:updated等等...
所以你不能通过$feed-&gt;id访问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

要获取第一个条目元素的 id,您可以使用 echo $children-&gt;entry[0]-&gt;id;
但随后您将点击&lt;media:group&gt; 元素及其子元素&lt;media:category&lt;media:player&gt; 等等...,它们位于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 脚本可以弄清楚如何处理这些数据。

【讨论】:

  • 这是我见过的对“命名空间”最好的解释。在我的 PHP 中,我目前正在以这种方式访问​​数据 — 指定 children('namespace'),但是您对我正在遵循的教程做了很好的说明。我不明白的一件事是如何在我的 HTML 中调用特定示例。我应该简单地从 PHP 中生成我所有的 HTML 吗?我希望默认加载主空间中的最新视频,然后是第 2-5 个视频的四个缩略图。当我单击缩略图时,我将使用 jQuery 将视频加载到主空间中。看来我需要精确访问节点[#],对吧?
  • 我觉得我正在修补这个问题。我想看看我是否正确。它说,对于变量“组”,查找命名空间 w3.org 的子元素,它们是数组中的第一个条目。然后,为“group”节点寻找命名空间 yahoo 的子节点。然后在 yahoo 命名空间中获取 group 的孩子?
  • 使用您的语法显示一个视频及其自己的缩略图,一切正常,但我遇到了同样的问题。我需要做 foreach 条目,存储这些值。然后在我的 HTML 中做 $entry[1]->$url 或类似的东西,但我不知道使这个工作的语法。还有什么想法吗?以下是当前相关的 PHP 和 HTML:droplr.com/lOEd0
  • 唷,你的编辑很详尽。我要睡在这上面。我很犹豫是否要放弃我迄今为止所做的 PHP 工作并从头开始。但是话又说回来,你上面的 PHP 解决方案真的让我迷失了。我真的需要明天把这个给客户。对我为什么不能围绕这个 YouTube API 和 XML 返回缺乏理解感到沮丧。我要睡了,但我明天会回来将这个答案标记为正确以及任何其他可以帮助我理解这些东西的答案。非常感谢你的帮助;到目前为止,它是无价的。
【解决方案2】:
$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 />';
}

【讨论】:

    【解决方案3】:

    试试$sxml-&gt;entry[4]-&gt;thumb 或者这方面的东西。

    AKA,要访问第一个条目 ID,您可以使用 $sxml-&gt;entry[4]-&gt;id

    基本上$sxml-&gt;entrySimpleXMLElement Objects 的数组。当您对它们进行 foreach 时,您将遍历每个对象并将其分配给 $entry,以便 $entry = $sxml-&gt;entry[0] 及以上。

    你可以这样:

    print_r($sxml);
    

    查看整个结构。这将告诉您访问它需要使用什么。

    【讨论】:

    • 我编辑了我的问题以澄清一件事。我实际上是使用内联回显在 PHP 之外的 HTML 中进行调用。我刚刚在 PHP 块中获得了 print_r 进行测试。很抱歉没有早点澄清这一点。非常感谢您到目前为止的帮助。
    • 太好了,非常感谢您澄清这里发生的事情。如果您没有注意到,我在这里的工资等级略高于我的工资等级,但我非常有兴趣了解为什么而不是如何。很高兴知道 foreach 正在遍历单独的对象。
    • 我 16 岁,无事可做。我的工资等级低于 :)
    • 我尝试在 $sxml->entry[0]->id 上执行 print_r 并得到 PHP 的虚无白屏。我已经在 $sxml 上完成了 print_r,我可以获取值,但我无法获取 specific 值。例如,来自 第三个实例 的 URL ='完整'持续时间='159' yt:格式='5'/>。如果有帮助的话,我还将包括我的一些 HTML (droplr.com/lN2dC) 和我目前所获得的屏幕截图 (droplr.com/lN34u)。
    • 我不完全确定问题出在哪里。随便玩玩,我相信你一定能找到它。
    【解决方案4】:

    最后,我做了两个 foreach 循环,一个通过 XML 提要运行,显示最近的 一个 条目。然后,我呼应了这个周围的物体来播放视频。

    另一方面,我浏览了最近的四个条目,返回缩略图列表的列表元素。

    现在,当我单击缩略图视频时,javascript 会处理将参数传递给主条目。现在,如何在接收到参数后重新加载该主对象,我对想法持开放态度。

    【讨论】:

      猜你喜欢
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      • 2013-10-20
      • 2013-06-04
      • 1970-01-01
      • 2020-05-05
      相关资源
      最近更新 更多