PHP é à quinta-feira – XML num Objecto
Mais uma quinta e mais um artigo para os interessados em PHP. A nível de direitos sobre o código, devo remeter-vos para o meu primeiro artigo desta rubrica aqui
Hoje trago-vos uma função que já me ajudou no passado, num projecto em que só podia trabalhar com PHP4 e tinha de fazer parsing de um ficheiro XML cuja sintaxe era conhecida.
Em PHP4 não existe a função simple_xml_load_string.
Esta função também pode ser usada em PHP5 quando o ficheiro XML não tem atributos, etc. pois usa menos recursos (dado que é menos dinâmica e menos complexa) do que a função que referi em cima.
<?php
function parseXMLtoObject($xml) {
$obj = new stdClass();
$xml = explode("\n",$xml);
$main_n = '';
foreach ($xml as $x) {
$first_n = false;
$close_n = false;
if ($x != '') {
$start_val = (strpos($x,">")+1);
$end_val = strrpos($x,"<") - $start_val;
$start_n = (strpos($x,"<")+1);
$end_n = strpos($x,">") - $start_n;
$n = strtolower(substr($x,$start_n,$end_n));
if (substr_count($x,"<") == 1) {
if (!empty($main_n) && !stristr($n,"/")) {
$submain_n = $n;
$first_n = true;
} else {
$main_n = $n;
$submain_n = '';
$first_n = true;
}
}
if (!empty($submain_n) && stristr($submain_n,"/")) {
$submain_n = '';
$first_n = false;
$close_n = true;
}
if (!empty($main_n) && stristr($main_n,"/")) {
$main_n = '';
$submain_n = '';
$first_n = false;
$close_n = true;
}
$value = substr($x,$start_val,$end_val);
if (!$close_n) {
if (empty($main_n)) {
$obj->$n = $value;
} else {
if ($first_n) {
if (empty($submain_n)) {
$obj->$main_n = new stdClass();
} else {
$obj->$main_n->$submain_n = new stdClass();
}
} else {
if (!empty($value)) {
if (empty($submain_n)) {
$obj->$main_n->$n = $value;
} else {
$obj->$main_n->$submain_n->$n = $value;
}
}
}
}
}
}
}
return $obj;
}
?>
Modo de utilização:
Converter Ficheiro XML $a para Object $o
<?php $a = “ficheiro.xml”; $xml = file_get_cont ents($a); $o = parseXMLtoObject($xml); //-- Agora podem visualizar a estrutura do $o desta forma: echo “<pre>”;print_r($o);echo “</pre>”;//-- Imprime a estrutura do objecto $o ?>
Qualquer dúvida ou sugestão, estão completamente à vontade.
Este artigo tem mais de um ano
Esta rubrica está a ganhar adeptos e podem esses adeptos (caso queiram) sugerir ao Bruno ou ao Pedro Pinto, alguma atenção especial sobre qualquer função.
Fica a sugestão.
Olá, pessoal!
Tenho umas pequenas dúvidas de PHP:
1 – A função:
while (list($var1, $var2) = each($array))
executa as funções “list” e “each” completamente sempre que verifica a condição “while”? Do tipo “for ($c = 0; $c < count($array); $c++)”. Aqui a função “count” é executada sempre.
2 – Para ficheiros XML muuuuito grandes (passados vários anos, fui adicionando muitos “filhos” a um nó, e o ficheiro ficou com 15 MB, por exemplo!), o PHP irá dar um “Fatal Error” de falta de memória. Como lidar com esses casos?
3 – Para um sistema de multi-language, o que recomenda usar para o ficheiro de linguagem? : XML? Arrays? Defines? – Quero saber o que é mais rápido.
4 – Para longos nós de XML, se eu fizer algo do estilo: $lista = (array)$objectoXML; isto converte de maneira muito viável, ou é um pouco pesado para o PHP?
São dúvidas que eu não consigo encontrar resposta na internet 🙁
Se alguém me responder, eu ficarei muito grato! 🙂
Obrigado.
Nuno Peralta
2 – Essa forma vai renovando a memória alocada nas variáveis $var1 e $var2, por isso pouco do que poderias fazer nesse caso já está feito, talvez o problema esteja no que fazes dentro desse ciclo e não na sua “declaração” em si. Altera o valor do memory_limit no php.ini para um valor um pouco maior.
Deduzo que o array $array tenha todas as linhas do ficheiro, logo chegando essa variável a um valor muito grande, pelo que podes considerar uma função que lê o ficheiro linha a linha e não tudo de uma só vez.
3 – Arrays e/ou Defines são mais rápidos de trabalhar (defines mais rápidos ainda, desde que não estejam sempre a ser declarados), porque não requerem um “acesso” ao disco para ler um ficheiro, mas o XML é muito melhor porque qualquer linguagem acede facilmente a ele. Dependerá do tamanho dos dados, provavelmente. Base de dados também será uma boa aposta
4 – É um bocado “pesado” usar casts, gastam muitas vezes recursos desnecessários, mas funciona. É uma questão de decidires as tuas prioridades, se um programa rápido e funcional, ou que simplesmente funcione, podendo usar alguns recursos a mais. Pessoalmente prefiro sempre ter o tipo de variável logo definido, e antes de a usar fazer uma verificação do tipo is_array() ou is_object().
A gratidão é o meu dinheiro espiritual 😉
2 – Bem… vou ter que ir aumentando a variavel do php.ini a cada ano que passa? =/
3 – Então o melhor é usar Arrays 🙂
4 – Eu quero programas viáveis, como é óbvio 🙂
Mas… se eu quero ver a intersecção (array_intersect()) de uma lista em XML, a função só funciona se a lista for uma array… se for objecto tenho mesmo que usar cast, não é? 🙁
Obrigado pelas suas respostas! 😀
Trata-me por tu, sff 🙂
2 – Se a lógica do programa se mantiver (o que necessita de recursos depende directamente do tamanho do ficheiro), terás de aumentar consoante necessitas, sim. Nesse caso, aconselho a mudares de lógica, como expliquei antes.
3 – Pessoalmente prefiro XML ou base de dados, mas a escolha é tua.
4 – Não conheço o caso específico, mas parece-me uma hipótese prática.
3 – Pois.. mas o XML será suficientemente viável para ser lido em TODAS as páginas, com muita gente a usar essas páginas? :S
Mesmo a base de dados, eu não gosto muito de a usar para coisas que podem ser feitas com XML normal… prefiro usá-la só para os usernames e passwords 🙂
Obrigadão pelas dicas!! Esclareceram-me algumas coisas que andavam a passear na minha cabeça*
3 – Não deverá ter grandes problemas, mas nesse caso talvez seja preferível a base de dados.
Tens uma outra solução melhor mas mais trabalhosa.
Um ficheiro externo que contém defines ou arrays com o que pretendes, mas esse ficheiro a ser gerado dinamicamente (com um cron diário ou assim) para estar actual.
De nada 🙂
Não me tinha apercebido do 1 como uma pergunta…
1 – As duas funções são sempre executadas, não percebo o que queres dizer com “completamente”, mas são executadas 🙂
Bem… o “completamente” é se para cada vez que as linhas dentro do while forem executadas, ele vai ler a array toda, ou se vai fazendo 1 a 1 (e aí executa as linhas para cada 1) até chegar ao final.
executa um a um, pois lê um apontador e não o array todo.
Se quiseres ler o array desde o início usando o each(), tens de usar o reset()
Sim, eu sei 🙂 eu uso sempre “reset()” antes do “each()”, para não haver problemas 😀
Desculpem la estragar a festa, mas onde é que isto é um tutorial?
Sinceramente acho que seria mais apropriado por isto numa secção de “snippets”, porque basicamente o que tens aqui é uma função (suponho que tenhas sido tu a criar) e pouco mais.
Vejo pouco atenção a explicar o código e detalhar mais os passos importantes da função.
Se isto é um tutorial deixa muito a desejar!
Gostaria de ver o codigo comentado 🙂