【问题标题】:Parsing XML using PHP使用 PHP 解析 XML
【发布时间】:2010-11-10 10:51:06
【问题描述】:

我一直在使用 PHP 解析 XML 时遇到问题,并且没有真正找到“正确的方法”,或者至少没有找到解析 XML 文件的标准化方法。

首先我试图解析这个:

  <item> 
     <title>2884400</title> 
     <description><![CDATA[ ><img width="126" alt="" src="http://userserve-ak.last.fm/serve/126/27319921.jpg" /> ]]></description> 
     <link>http://www.last.fm/music/+noredirect/Beatles/+images/27319921</link> 
     <author>anne710</author> 
     <pubDate>Tue, 21 Apr 2009 16:12:31 +0000</pubDate> 
     <guid>http://www.last.fm/music/+noredirect/Beatles/+images/27319921</guid> 
     <media:content url="http://userserve-ak.last.fm/serve/_/27319921/Beatles+2884400.jpg" fileSize="13065" type="image/jpeg" expression="full"  width="126" height="126" /> 
     <media:thumbnail url="http://userserve-ak.last.fm/serve/126/27319921.jpg" type="image/jpeg" width="126" height="126" /> 
  </item> 

我正在使用此代码:

$doc = new DOMDocument();
$doc->load('http://ws.audioscrobbler.com/2.0/artist/beatles/images.rss');
$arrFeeds = array();
foreach ($doc->getElementsByTagName('item') as $node) {
    $itemRSS = array ( 
        'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
        'desc' => $node->getElementsByTagName('description')->item(0)->nodeValue,
        'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,
        'date' => $node->getElementsByTagName('pubDate')->item(0)->nodeValue
        );
    array_push($arrFeeds, $itemRSS);
}

现在我想获取“media:content”和“media:thumbnail”url 属性,我该怎么做?现在我认为我应该使用 DOMElement::getAttribute 但我还没有设法让它工作:/ 任何人都可以对此有所了解,并让我知道这是否是解析 XML 的好方法?

问候, 沙迪

【问题讨论】:

  • 这整个问题/线程非常糟糕。问题是缺乏对命名空间的理解。我建议任何阅读本文的人了解 XML 命名空间。人们在下面提到了这一点。问题是 media:content 表示属于“媒体”命名空间的“内容”标签,而不是默认命名空间(这是您要查询的)。

标签: php xml parsing domdocument


【解决方案1】:

您可以按照其他海报的建议使用SimpleXML,但您需要使用children() 和attributes() 函数以便deal with the different namespaces

示例(未经测试):

$feed = file_get_contents('http://ws.audioscrobbler.com/2.0/artist/beatles/images.rss');
$xml = new SimpleXMLElement($feed);
foreach ($xml->channel->item as $item) {
    foreach ($item->children('http://search.yahoo.com/mrss' as $media_element) {
        var_dump($media_element);
    }
}

或者,您可以使用 XPath(同样,未经测试):

$feed = file_get_contents('http://ws.audioscrobbler.com/2.0/artist/beatles/images.rss');
$xml = new SimpleXMLElement($feed);
$xml->registerXPathNamespace('media', 'http://ws.audioscrobbler.com/2.0/artist/beatles/images.rss');
$images = $xml->xpath('/rss/channel/item/media:content@url');
var_dump($images);

【讨论】:

    【解决方案2】:

    试试这个。它会正常工作的。

    $doc = new DOMDocument();
    $doc->load('http://ws.audioscrobbler.com/2.0/artist/beatles/images.rss');
    $arrFeeds = array();
    foreach ($doc->getElementsByTagName('item') as $node) {
        $itemRSS = array ( 
            'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
            'desc' => $node->getElementsByTagName('description')->item(0)->nodeValue,
            'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,
            'date' => $node->getElementsByTagName('pubDate')->item(0)->nodeValue,
            'thumbnail' => $node->getElementsByTagName('thumbnail')->item(0)->getAttribute('url')
        );
        array_push($arrFeeds, $itemRSS);
    }
    

    【讨论】:

      【解决方案3】:

      这就是我最终使用 XMLReader 完成的方式:

      <?php
      
      define ('XMLFILE', 'http://ws.audioscrobbler.com/2.0/artist/vasco%20rossi/images.rss');
      echo "<pre>";
      
      $items = array ();
      $i = 0;
      
      $xmlReader = new XMLReader();
      $xmlReader->open(XMLFILE, null, LIBXML_NOBLANKS);
      
      $isParserActive = false;
      $simpleNodeTypes = array ("title", "description", "media:title", "link", "author", "pubDate", "guid");
      
      while ($xmlReader->read ())
      {
          $nodeType = $xmlReader->nodeType;
      
          // Only deal with Beginning/Ending Tags
          if ($nodeType != XMLReader::ELEMENT && $nodeType != XMLReader::END_ELEMENT) { continue; }
          else if ($xmlReader->name == "item") {
              if (($nodeType == XMLReader::END_ELEMENT) && $isParserActive) { $i++; }
              $isParserActive = ($nodeType != XMLReader::END_ELEMENT);
          }
      
          if (!$isParserActive || $nodeType == XMLReader::END_ELEMENT) { continue; }
      
          $name = $xmlReader->name;
      
          if (in_array ($name, $simpleNodeTypes)) {
              // Skip to the text node
              $xmlReader->read ();
              $items[$i][$name] = $xmlReader->value;
          } else if ($name == "media:thumbnail") {
              $items[$i]['media:thumbnail'] = array (
                      "url" => $xmlReader->getAttribute("url"),
                      "width" => $xmlReader->getAttribute("width"),
                      "height" => $xmlReader->getAttribute("height"),
                      "type" => $xmlReader->getAttribute("type")
              );
          } else if ($name == "media:content") {
              $items[$i]['media:content'] = array (
                      "url" => $xmlReader->getAttribute("url"),
                      "width" => $xmlReader->getAttribute("width"),
                      "height" => $xmlReader->getAttribute("height"),
                      "filesize" => $xmlReader->getAttribute("fileSize"),
                      "expression" => $xmlReader->getAttribute("expression")
              );
          }
      }
      
      print_r($items);
      echo "</pre>";
      
      ?>
      

      【讨论】:

        【解决方案4】:
        <?php
        
        #Convert the String Into XML
        $xml = new SimpleXMLElement($_POST['name']);
        
        #Itterate through the XML for the data 
        
        $values = "VALUES('' , ";
        foreach($xml->item as $item)
        {
         //you now have access to that aitem
        }
        
        ?>
        

        【讨论】:

        • hmmm,这并没有真正奏效,我尝试放置 url 而不是 $_POST 但它没有获取文件,我将文件放入变量并将其传递给 simplexmlelement 但是$item 里面仍然没有任何东西。
        • 这实际上是我的代码中的代码 sn-p 的一部分。我应该提到您需要更改 $xml->item 因为它与您获得的 xml 提要有关。我会查看 SimpleXMLElement 文档——但这就是我用来处理从 Adob​​e Flex 发送的 XML 的文档
        【解决方案5】:

        尝试使用 SimpleXML:http://us2.php.net/simplexml

        【讨论】:

        • 通过 simplexml 运行数据似乎没有帮助,它没有获取任何
        • 我也建议使用 SimpleXML
        【解决方案6】:

        你会想要这样的:

        'content' => $node->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'content')->item(0)->getAttribute('url');
        'thumbnail' => $node->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'thumbnail')->item(0)->getAttribute('url');
        

        我相信这会奏效,我已经有一段时间没有做过这样的事情了。

        【讨论】:

        • backend.userland.com/creativeCommonsRssModule" xmlns:media="search.yahoo.com/mrss"> 那么如何实现呢?!
        • [Mon Jul 13 23:13:04 2009] [error] [client xxx.xxx.xxx.xxx] PHP 致命错误:在非对象上调用成员函数 getAttribute() /v2.php 第 73 行
        • 这是一个很好的解决方案,只有一个令人困惑的事情; getElementsByTagNameNS 通常与 $node 无关(它是迭代的一部分),但它与 XML 的 Document Root 相关,与主 DOM 对象相关。如果变量$xml = new DOMDocument();,那么它将是这样工作的:$content = $xml-&gt;getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'content')-&gt;item($i);
        【解决方案7】:

        如果提要缺少thumbnail 之类的条目,您可能会收到错误Call to a member function getAttribute() on a non-object,所以虽然我喜欢@Helder Robalo 的回答,但您应该在尝试使用getAttribute() 之类的东西之前检查以确保节点存在:

        <?php
        
        header('Content-type: text/plain; charset=utf-8');
        
        $doc = new DOMDocument();
        $doc->load('http://ws.audioscrobbler.com/2.0/artist/beatles/images.rss');
        $arrFeeds = array();
        foreach ($doc->getElementsByTagName('item') as $node) {
            $itemRSS = array (
                'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
                'desc' => $node->getElementsByTagName('description')->item(0)->nodeValue,
                'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,
                'date' => $node->getElementsByTagName('pubDate')->item(0)->nodeValue
            );
        
            if( sizeof($node->getElementsByTagName('thumbnail')->item(0)) > 0 )
            {
                $itemRSS['thumbnail'] = $node->getElementsByTagName('thumbnail')->item(0)->getAttribute('url');
            }
            else
            {
                $itemRSS['thumbnail'] = '';
            }
        
            array_push($arrFeeds, $itemRSS);
        }
        
        
        print_r($arrFeeds);
        

        【讨论】:

          【解决方案8】:

          Media:content 属性实际上很容易通过 SIMPLE XML 获得

          if(!@$x=simplexml_load_file($feed_url)){
          
          }
          else
          {
            foreach($x->channel->item as $entry)
            {
              $media = $entry->children('http://search.yahoo.com/mrss/')->attributes();
              $url = (string) $media['url'];
            }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-07-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多