Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

gmps

[Resolvido] ler rss

Recommended Posts

galera..to tentando ler o conteudo de rss com DOMDocument, mas so esta pegando o primeiro elemento "item", porque?

 

$doc = new DOMDocument('1.0', 'utf-8');
$doc -> formatOutput = true;
$doc->load('http://www.amvideolocadora.com.br/rss.php');
$itemnodes = $doc->getElementsByTagName( "item" );
$nodes = $itemnodes->item(0)->getElementsByTagName( "*" );
for ( $i = 0; $i < $nodes->length; $i++ ) {
    echo "ELEMENTO = ".$nodes->item( $i )->nodeName;
    echo "<br>";
    echo "CONTEUDO = ".$nodes->item( $i )->nodeValue;
    echo "<br><br>";
}

[]´z

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sem dúvida a SimpleXML é bem melhor e mais fácil de se usar... Existem vários exemplos na net, dá um olhada no Google. ;)

 

Mais fácil de usar eu não vou falar nada, mas melhor não é não, heheheh

 

Bom, ai vai um leitor de RSS completo:

 

Classe Item:

class Item {
	/**
	 * Dados do item
	 * @var string
	 */
	protected $data;

	/**
	 * Constroi objeto Item
	 */
	public function __construct(){
		$this->data		= array();
	}

	/**
	 * Recupera dinamicamente uma propriedade do canal
	 * @param string $name O nome da propriedade
	 * @return mixed O valor da propriedade
	 */
	public function __get( $name ){
		$ret = null;

		if ( isset( $this->data[ $name ] ) ){
			$ret = $this->data[ $name ];
		}

		return( $ret );
	}

	/**
	 * Define dinamicamente o valor de uma propriedade
	 * @param string $name O nome da propriedade
	 * @param mixed $value O valor da propriedade
	 */
	public function __set( $name , $value ){
		$this->data[ $name ] = $value;
	}
}

Classe Channel:

final class Channel extends Item {
	/**
	 * Lista de itens
	 * @var array
	 */
	private $items;

	/**
	 * Constroi objeto Channel
	 */
	public function __construct(){
		parent::__construct();
		$this->items	= array();
	}

	/**
	 * Adiciona um novo item ao canal
	 * @param Item $item O novo item
	 */
	public function addItem( Item $item ){
		$this->items[] = $item;
	}

	/**
	 * Recupera um item na posição $pos
	 * @param integer $pos A posição do item
	 * @return Item
	 */
	public function getItemAt( $pos ){
		$ret = null;

		if ( isset( $this->items[ (int) $pos ] ) ){
			$ret = $this->items[ (int) $pos ];
		} else {
			throw new InvalidArgumentException( sprintf( "Não existe um item em %d" , $pos ) );
		}

		return( $ret );
	}

	/**
	 * Recupera a lista de itens da fonte de notícias
	 * @return array
	 */
	public function items(){
		$ret = $this->items;

		return( $ret );
	}
}

Classe RSS:

final class RSS {
	/**
	 * DOMDocument que irá receber a fonte de notícias
	 * @var DOMDocument
	 */
	private $dom;

	/**
	 * Definição da fonte de notícias
	 * @var Channel
	 */
	public $channel;

	/**
	 * Lê um rss e interpreta o conteúdo
	 * @param string $uri A localização da fonte de notícias
	 */
	public function __construct( $uri ){
		$this->dom = new DOMDocument();
		$this->dom->load( $uri );
		$this->parseChannel();
	}

	/**
	 * Interpreta o nó channel do rss
	 */
	private function parseChannel(){
		$xpath	= new DOMXPath( $this->dom );
		$nodes	= $xpath->query( "//rss/channel/*" );

		$this->channel = new Channel();

		foreach ( $nodes as $node ){
			$name = $node->nodeName;

			switch ( $name ){
				case "item" : $this->channel->addItem( $this->parseItem( $node ) ); break;
				default :
						$this->channel->$name = $node->nodeValue; break;
			}
		}
	}

	/**
	 * Interpreta os nós item do canal
	 * @param DOMElement $element O elemento item que será interpretado
	 * @return Item O item processado
	 */
	private function parseItem( DOMElement $element ){
		$xpath	= new DOMXPath( $this->dom );
		$nodes	= $xpath->query( "./*" , $element );
		$item	= new Item();

		foreach ( $nodes as $node ){
			$name = $node->nodeName;
			$item->$name = $node->nodeValue;
		}

		return( $item );
	}
}

Para usar:

require_once( "Item.php" );
require_once( "Channel.php" );
require_once( "RSS.php" );

$rss = new RSS( "http://forum.imasters.com.br/index.php?app=core&module=global&section=rss&type=forums&id=1" );

printf( "Titulo: %s<br />" , $rss->channel->title );
printf( "Descrição: %s<br />" , $rss->channel->description );
printf( "Link: %s<br />" , $rss->channel->link );

$items = $rss->channel->items();

for ( $i = 0 , $t = count( $items ) ; $i < $t ; $i++ ){
	$item = $items[ $i ];

	printf( "Item %d<br />" , $i );
	printf( "Titulo: %s<br />" , $item->title );
	printf( "Descricao: %s<br />" , $item->description );
	printf( "link: %s<br />" , $item->link );
	printf( "autor: %s<br />" , $item->author );
	printf( "----------------------------------------------<br />" );
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

@João Batista Neto

Desculpa contrariar mas.. Você acha mais simples incluir três arquivos e chamar três classes diferentes?

 

Como eu disse:

 

Mais fácil de usar eu não vou falar nada, mas melhor não é não, heheheh

 

Não vou discutir que o simpleXML é simple, o ponto que levantei é que ele é fraco e oferece poucos recursos. Se você vai fazer uma coisa simple ele é PERFEITO, porém se você precisar trabalhar com algo maior você deve cogitar o DOM e se for maior ainda você deve pensar em utilizar SAX.

É tudo uma questão de quando utilizar.

 

Agora, quanto a chamar três classes direfentes, bom isso é apenas uma questão de organização pessoal, depois de incluir as classes o uso é EXATAMENTE igual:

 

$rss = simplexml_load_file( 'http://forum.imasters.com.br/index.php?app=core&module=global&section=rss&type=forums&id=1' );

printf( "Titulo: %s<br />" , $rss->channel->title );
printf( "Descrição: %s<br />" , $rss->channel->description );
printf( "Link: %s<br />" , $rss->channel->link );

$items = $rss->channel->item;

for ( $i = 0 , $t = count( $items ) ; $i < $t ; $i++ ){
	$item = $items[ $i ];

	printf( "Item %d<br />" , $i );
	printf( "Titulo: %s<br />" , $item->title );
	printf( "Descricao: %s<br />" , $item->description );
	printf( "link: %s<br />" , $item->link );
	printf( "autor: %s<br />" , $item->author );
	printf( "----------------------------------------------<br />" );
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ta bom, mas o que o usuário quer? Ele quer ler um RSS.

E convenhamos, precisa disso tudo para ler um RSS, sendo que o PHP 5+ já vem com a LIB SimpleXML, que resolve todos os problemas do usuário?

 

Bom, essa é minha última resposta quanto a esse ponto.

 

1. Se você prestar atenção no tópico ler rss DOMDocument, ele quer ler rss DOMDocument

2. A simpleXML não resolve todos os problemas do usuário, pode até resolver esse caso, mas definitivamente NÃO resolve todos os problemas.

 

Gente, numa boa...

Total perda de tempo isso, o kara tava com uma dúvida eu ajudei, se ele achar que minha ajuda foi útil ele usa se ele achar que eu mais atrapalhei que ajudei, então minhas desculpas a ele.

Agora, um moderador e um mod. trainee entrar em um tópico para não ajudar o kara e ainda me questionar por ter ajudado ???

Que é isso, "Se tiver disponivel a lib SimpleXML, tenta usar ela." ou "Existem vários exemplos na net, dá um olhada no Google." pô, o kara entrou aqui pedindo ajuda e logo na primeira reply fala para ele, olha, aqui está cheio de desenvolvedores mas procura no google que você vai encontrar o que precisa.

Se é assim nem é necessário existir um fórum.

Compartilhar este post


Link para o post
Compartilhar em outros sites

bom galera...acho que nao precisamos discutir se vamos usar uma ou outra...eu optei pela DOM porque foi oq eu achei melhor, estou usando o PHP5 e tambem poderia utilizar a simplexml, mas acabei optando pela DOM.

 

Obrigado pelos codigos João Batista Neto.

 

Eu tenho um codigo aqui que ERA par pegar valores do RSS e ATOM, mas nao sei o motivo pelo qual ele nao pega elementos do atom como <content:encoded>, <dc:creator> etc, elementos simples como title, description, pubDate.. eu consigo pegar sem problemas.

 

Encontrei varios codigos na internet, alguns nao exibiam o conteudo quando tinha CDATA no codigo, ou entao agrupava os elementos das categorias, ou pegava somente uma categoria e as outras nao, bom, nao serviam para mim, porque eu PRECISO capturar TODAS as categorias de um item.

 

Segue o codigo abaixo que nao pega os elementos do atom que eu informei:

 

function rss_to_array($tags, $array, $url) {
  /*RSS and ATOM*/
  $doc = new DOMdocument();
  @$doc->load($url);
  $rss_array = array();
  foreach($tags as $tag) {
    if ($doc->getElementsByTagName($tag)) {
      foreach($doc->getElementsByTagName($tag) AS $node) {
        $items = array();
        foreach($array AS $key => $values) {
          $items[$key] = array();
          foreach($values as $value) {
            if ($itemsCheck = $node->getElementsByTagName($value)) {
              for( $j=0 ;  $j < $itemsCheck->length; $j++ ) {
                if (($attribute = $itemsCheck->item($j)->nodeValue) != "") {
                  $items[$key][] = utf8_decode($attribute);
                } else if ($attribute = $itemsCheck->item($j)->getAttribute('term')) {
                  $items[$key][] = utf8_decode($attribute);
                } else if ($itemsCheck->item($j)->getAttribute('rel') == 'alternate') {
                  $items[$key][] = $itemsCheck->item($j)->getAttribute('href');
                }
              }
            }
          }
        }
        array_push($rss_array, $items);
      }
    }
  }
  return $rss_array;
}

$rss_item_tags = array('item', 'entry');

$rss_tags = array(
  'title' => array('title'),
  'description' => array('description', 'content', 'summary'),
  'link' => array('link', 'feedburner'),
  'category' => array('category'),
  'pubDate' => array('pubDate'),
  'content' => array('content'),
  'content:encoded' => array('content:encoded')
);

$url = utf8_encode("http://feeds.feedburner.com/sedentario"); // apenas exemplo de um ATOM

$rssfeed = rss_to_array($rss_item_tags, $rss_tags, $url);

print_r($rssfeed);

alguem sabe o pq?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado pelos codigos João Batista Neto.

 

;)

 

 

Eu tenho um codigo aqui que ERA par pegar valores do RSS e ATOM, mas nao sei o motivo pelo qual ele nao pega elementos do atom como <content:encoded>, <dc:creator> etc, elementos simples como title, description, pubDate.. eu consigo pegar sem problemas.

 

Encontrei varios codigos na internet, alguns nao exibiam o conteudo quando tinha CDATA no codigo, ou entao agrupava os elementos das categorias, ou pegava somente uma categoria e as outras nao, bom, nao serviam para mim, porque eu PRECISO capturar TODAS as categorias de um item.

 

alguem sabe o pq?

 

Bom, o prefixo content, dc está relacionado a um namespace e talvez isso esteja confundindo o seu parser.

Mas as três classes que mandei antes fazem o trabalho completo, sem precisar de nenhuma modificação:

 

$rss = new RSS( "http://feeds.feedburner.com/sedentario" );

$items = $rss->channel->items();

for ( $i = 0 , $t = count( $items ) ; $i < $t ; $i++ ){
	$item = $items[ $i ];

	printf( "Title: %s<br />" , $item->title );
	printf( "Link: %s<br />" , $item->title );
	printf( "dc:creator: %s<br />" , $item->__get( "dc:creator" ) );
	printf( "wfw:commentRss: %s<br />" , $item->__get( "wfw:commentRss" ) );
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

entendi...entao...esta este seu codigo com esta url: http://www.amvideolocadora.com.br/rss.php não é atom

 

eu testei aqui e nao pega todas as categorias, como nos outros scripts que testei, pega somente uma vez o elemento <category>

 

$rss = new RSS( "http://www.amvideolocadora.com.br/rss.php" );

$items = $rss->channel->items();

for ( $i = 0 , $t = count( $items ) ; $i < $t ; $i++ ){
        $item = $items[ $i ];

        printf( "Title: %s<br />" , $item->title );
        printf( "Link: %s<br />" , $item->title );
	printf( "category: %s<br />" , $item->__get( "category" ) );
}

seria assim para pegar as categorias ne? um rss/atom pode ter mais de um elemento <category> ...

 

=/

Compartilhar este post


Link para o post
Compartilhar em outros sites

entendi...entao...esta este seu codigo com esta url: http://www.amvideolocadora.com.br/rss.php não é atom

 

eu testei aqui e nao pega todas as categorias, como nos outros scripts que testei, pega somente uma vez o elemento <category>

 

$rss = new RSS( "http://www.amvideolocadora.com.br/rss.php" );

$items = $rss->channel->items();

for ( $i = 0 , $t = count( $items ) ; $i < $t ; $i++ ){
        $item = $items[ $i ];

        printf( "Title: %s<br />" , $item->title );
        printf( "Link: %s<br />" , $item->title );
	printf( "category: %s<br />" , $item->__get( "category" ) );
}

seria assim para pegar as categorias ne? um rss/atom pode ter mais de um elemento <category> ...

 

=/

 

Certo, na classe item, modifique o médoto __set( $name , $value ) para:

 

/**
 * Define dinamicamente o valor de uma propriedade
 * @param string $name O nome da propriedade
 * @param mixed $value O valor da propriedade
 */
public function __set( $name , $value ){
	if ( isset( $this->data[ $name ] ) ){
		if ( gettype( $this->data[ $name ] ) == "array" ){
			$this->data[ $name ][] = $value;
		} else {
			$temp = $this->data[ $name ];
			$this->data[ $name ] = array( $temp , $value );
		}
	} else {
		$this->data[ $name ] = $value;
	}
}

Com isso, qualquer nó que tiver mais de uma ocorrência será tratado como uma matriz

Compartilhar este post


Link para o post
Compartilhar em outros sites

uma duvida...agora o category fica como array

 

category: Array

 

 

como que tem que fazer com esses "novos" elementos?

Compartilhar este post


Link para o post
Compartilhar em outros sites

uma duvida...agora o category fica como array

 

category: Array

 

 

como que tem que fazer com esses "novos" elementos?

 

Todo elemento que for uma lista (ex: category que pode ter vários) ele será tratado como matriz, para acessar o conteúdo é igual a uma matriz normal:

 

$rss = new RSS( "http://www.amvideolocadora.com.br/rss.php" );
$item = $rss->channel->getItemAt( 1 ); //Acesso direto ao item 1 (é o segundo item pq começa com 0)

printf( "Title: %s<br />" , $item->title ); //Uma história contada em games
printf( "link: %s<br />" , $item->link ); //http://feedproxy.google.com/~r/sedentario/~3/gic5tX3HZXs/uma-historia-contada-em-games-2-17655
printf( "comments: %s<br />" , $item->comments ); //Fri, 17 Jul 2009 13:31:15 +0000
printf( "pubDate: %s<br />" , $item->pubDate ); //Eightbits
printf( "category: %s<br />" , $item->category[ 0 ] ); //games
printf( "category: %s<br />" , $item->category[ 1 ] ); //vídeos

Ou então continuando com o loop:

$rss = new RSS( "http://www.amvideolocadora.com.br/rss.php" );

$items = $rss->channel->items();

for ( $i = 0 , $t = count( $items ) ; $i < $t ; $i++ ){
	$item = $items[ $i ];

	printf( "Title: %s<br />" , $item->title );
	printf( "link: %s<br />" , $item->link );
	printf( "comments: %s<br />" , $item->comments );
	printf( "pubDate: %s<br />" , $item->pubDate );

	if ( gettype( $item->category ) == "array" ){
		for ( $j = 0 , $k = count( $item->category ) ; $j < $k ; $j++ ){
			printf( "category %d<br />" , $j , $items->category[ $j ] );
		}
	} else {
		printf( "category: %s<br />" , $item->category );
	}
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

opa...nesse ultimo codigo o certo no loop da categoria seria

 

printf( "category %d<br />" , $j , $item->category[ $j ] );

 

e nao com $items ne?

 

so a ultima coisa...e o esquema de utf8 e decode? preciso dar um uft8 para qdo baixar a leitura e depois um decode para exibir as informações, pq esta com problemas de letra... ex: Operação Valquíria

 

[EDIT]

consegui arrumar os acentos, no RSS.php na função parseItem fiz:

foreach ( $nodes as $node ){
  $name = $node->nodeName;
  $item->$name = utf8_decode($node->nodeValue);
}

 

e deu certo.

 

bom...testei aqui, consegui pegar mais de um elemento na categoria...oq eu tenho a dizer é MUITO OBRIGADO e é por isso que gosto desse forum...valeu cara...qualquer coisa eu volto a te atormentar aqui..acredito que este post vai ser util para mtas pessoas...

 

vlw

Compartilhar este post


Link para o post
Compartilhar em outros sites

opa...nesse ultimo codigo o certo no loop da categoria seria

 

printf( "category %d<br />" , $j , $item->category[ $j ] );

e nao com $items ne?

 

opz... :P

 

bom...testei aqui, consegui pegar mais de um elemento na categoria...oq eu tenho a dizer é MUITO OBRIGADO e é por isso que gosto desse forum...valeu cara...qualquer coisa eu volto a te atormentar aqui..acredito que este post vai ser util para mtas pessoas...

 

vlw

 

Abraços...

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.