Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá amigos tudo bem?
Estou apanhando para conseguir ler os campos de um XML e jogar SOMENTE os que eu quero para um array.
Na função abaixo comecei fazendo o que EU achava certo, mas parei no meio (onde está comentado) por não saber como continuar. Alguém pode dar uma luz?
$retorno = array();
function criaArray($q) {
$result = file_get_contents("http://search.4shared.com/network/searchXml.jsp?searchExtention=mp3&q=" . $q);
$xml = simplexml_load_string($result);
foreach ($xml->{'result-files'}->file as $musicas) {
foreach ($musicas as $key => $value) {
/*Aqui faz algo que retorna a variavel $retorno em um array do tipo
* array(
* array('nome' => 'Nome da musica', 'url' => 'URL do campo flash-preview-url do xml'),
* array('nome' => 'Nome da musica', 'url' => 'URL do campo flash-preview-url do xml'),
* array('nome' => 'Nome da musica', 'url' => 'URL do campo flash-preview-url do xml'),
* array('nome' => 'Nome da musica', 'url' => 'URL do campo flash-preview-url do xml'),
*
* );
*
*
*/
}
}
}
Abaixo um exemplo de XML que a URL retorna.
<!--<?xml version="1.0" encoding="UTF-8"?>-->
<search-result>
<query>mixverao</query>
<total-files>1</total-files>
<page-number>1</page-number>
<pages-total>0</pages-total>
<start>0</start>
<files-per-page>10</files-per-page>
<files-approx-count>1</files-approx-count>
<result-files>
<file>
<name>Dj_Gabriel_Cabral_(MixVerao_Janeiro_10).mp3</name>
<description>DJ Gabriel Cabral (MixVerão)</description>
<downloads-count>60</downloads-count>
<upload-date-format>hh:mm dd-MM-yyyy</upload-date-format>
<upload-date>10:18 20-01-2010</upload-date>
<url>http://www.4shared.com/mp3/UgEfe-pE/Dj_Gabriel_Cabral__MixVerao_Ja.htm</url>
<preview-url />
<flash-preview-url>http://dc168.4shared.com/img/202795439/1fbf78ff/dlink__2Fdownload_2FUgEfe-pE_3Ftsid_3D20120413-045520-822fac8a/preview.mp3?dsid=1fs6qo.e81d3c0fb688680389a5fb52e5edec8a</flash-preview-url>
<user>DJ Gabriel Cabral</user>
<profile-url>http://www.4shared.com/u/QVyX58Co/DJ_Gabriel_Cabral.html</profile-url>
<size>10,670 KB</size>
</file>
</result-files>
</search-result>É, to vendo o lindo poder desse DOMDocument! :lol:
Esse DOMDocument é show heim! e sobre velocidade? ele é tão rápido quanto os demais recursos?
Não, a DOMDocument é consideravelmente mais devagar do que a SimpleXML pelo fato de a responsabilidade de cada componente ser de uma classe nativa diferente.
Pelo exemplo do Carlos você vê apenas a DOMDocumment mas, por exemplo, DOMDocumment::getElementsByTagName() retorna um DOMNodeList o qual através de seu método DOMNodelist::item() retorna um DOMNode.
Para o bê-a-bá, você não precisa entender toda mecânica da coisa, mas conforme a necessidade aumenta, conhecer cada componente é fundamental, até mesmo para você saber quais métodos estarão disponíveis e em que parte do código.
Bons estudos :thumbsup:
Usando o DOMDocumment, como pegar em uma variavel o campo do XML (total-files)? tenho que fazer outro for? ou é só
$numArquivos = $DOMDocument->getElementsByTagName('total-files');
Não, você não precisa de outro loop. Eu poderia orientar você a ler os métodos da DOMDocumment, mas seria crueldade demais para uma coisa tão simples:
$DOMDocument -> getElementsByTagName( 'total-files' ) -> item( 0 ) -> nodeValue
Obs: a variável $DOMDocument é a mesma do exemplo do Carlos.
E veja só como esse exemplo ilustra bem a separação de responsabilidades que eu citei.
Cada método invocado pertence à uma classe diferente, mas como cada uma é o retorno da anterior, a cadeia de invocação ("flechas sequenciais") pode ser usada até que cheguemos à propriedade pública com a informação em si.
Muito obrigado Bruno! Estou lendo o tutorial http://forum.imasters.com.br/topic/432995-domdocument-xml-php-parte-1/ muito bom! vamos ver se aprendo isso hehehe :thumbsup:
Olha eu outra vez!
Com a ajuda do @Bruno Augusto e do @Carlos Coelho fiz a classe abaixo para um projeto que quero liberar, mas estou com um problema. O 4shared é horrível para organizar seus ficheiros. Determinadas buscas podem retornar elementos que não são músicas. Para resolver isso é fácil, basta olhar se no node -> flash-preview-url possui alguma valor, caso não tenha significa que o elemento não é uma música então não deve entrar no array de retorno.
Tentei fazer isso com o unset() porém como é um array multidimensional ele retorna sempre os outros arrays mesmo nulos.
Dúvida: Como faço então para que só entrem no array resultado os elementos que realmente tiverem um flash-preview-url?
Olha a classe que fiz ai:
<?php
/**
* Classe que realiza uma busca e retorna
* os dados em um array para posterior manipulação.
*
* @version 0.1
* @access public
*/
Class Busca {
/**
* Controla se existe algum erro na busca
*
* @access public
* @name $erro
*/
public $erro = FALSE;
/**
* Armazena o resultado da busca feito pelo usuário
*
* @access public
* @name $resultado
*/
public $resultado = array();
/**
* Retorna Array com nome e url das músicas encontradas
*
* @param string $busca a busca do usuário
* @param int $pag a pagina ser listada, por padrão a primeira
*
* @return array
*/
public function fazBusca($busca, $pag = 1) {
$busca = urlencode($busca); //Converte caracteres não-alfanuméricos
$DOMDocument = new DOMDocument('1.0', 'UTF-8');
$DOMDocument->preverseWhiteSpace = TRUE;
$DOMDocument->load('http://search.4shared.com/network/searchXml.jsp?searchExtention=mp3&q=' . $busca . '&start=' . $pag);
$totalArquivos = $DOMDocument->getElementsByTagName('total-files')->item(0)->nodeValue;
if($totalArquivos) {
foreach ($DOMDocument->getElementsByTagName('file') as $arquivo) {
$temp = array();
foreach ($arquivo->childNodes as $campo) {
if ($campo->nodeName == 'name') {
$temp['nome'] = $this->formataNome($campo->nodeValue);
}
if ($campo->nodeName == 'flash-preview-url' && $campo->nodeValue <> NULL) {
$temp['download'] = $this->encodeURL($campo->nodeValue);
$temp['url'] = $campo->nodeValue;
}else{
unset($temp); // Não adianta :(
}
}// segundo foreach
$this->resultado[] = $temp;
}// Primeiro foreach
} else {
$this->erro = TRUE;
}
}
// class
/**
* Retorna a url de download codificada em base64
*
* @param string $url URL do link de download
*
* @return string
*/
public function encodeURL($url) {
return base64_encode($url);
}
/**
* Remove a extensão dos nomes e formata
*
* @param string $nome nome completo encontrado no 4shared
*
* @return string
*/
public function formataNome($nome) {
return str_replace('.mp3', '', $nome);
}
}
Desculpa ai as ratas típicas de um iniciante, mas acredito que o código está ate bom.
Use :seta: empty
if( $campo->nodeName == 'flash-preview-url' && ! empty( $campo->nodeValue )
{
// faz alguma coisa
Da linha 58 a linha 53 eu tenho:
if ($campo->nodeName == 'flash-preview-url' && $campo->nodeValue <> NULL) {
$temp['download'] = $this->encodeURL($campo->nodeValue);
$temp['url'] = $campo->nodeValue;
} else {
unset($temp);
}
Isso faz com que os valores só sejam jogados na variável, se o flash-preview-url existir. ate aqui tudo ótimo, mas o nome, mesmo sem o flash-preview-url, existe.
minha ideia foi usar um if para testar antes de atribuir o nome, mas ai descobri que depois de passar por um node, ele não volta, então se o teste do nome estiver dentro de um teste do node da url nao rola.
então o que quero mesmo é, que o teste ao encontrar o node nulo destrua o array atual. como ele é multidimensional so a tual é eliminada, caso tenha valores em outros nodes o retorno é normal, mas ignora todo node sem a bendita url.
Pegou?
array(
array( ' essa tem dados tanto nome quanto url '),
array( ' opa essa nao tem todos dados deve ser eliminada ' ),
array(' essa tb esta ok ')
)
Usando DOMDocument é fácil :thumbsup:
foreach( $DOMDocument->getElementsByTagName( 'file' ) as $content )
{
Saída
array
0 =>
array