Mesmo as críticos mais rigorosos podem concordar que quando se trata de trabalhar com tecnologias baseadas em XML, pode ser muito pior que trabalhar com o PHP. Poucas linguagens de programação oferecem a profundidade e amplitude de extensões XML de PHP:
- SimpleXML e XMLReader para processamento XML básico
- XSLT e XML-DAS para transformação XML
- SAX para análise baseada em evento
- DOM para análise baseada em árvore
- WDDX para serialização de dados
- XMLWriter para criação de documento XML dinâmica
Todas essas extensões se baseiam na biblioteca libxml2, e fornecem uma base robusta e unificada para processamento XML em PHP.
Dito isso, uma tecnologia baseada em XML importante não aparece na lista acima: o XQuery. Enquanto que o SimpleXML inclui algum suporte XQuery básico, ele não é (nem deveria ser) um processador XQuery completo. Por isso, você deve olhar mais longe, para a PHP Extension Community Library (PECL), que contém uma extensão para o processador Zorba XQuery. Esta extensão pode ser usada para incluir suporte de processamento XQuery completo em recursos para PHP.
Este artigo examina a extensão PHP do Zorba em detalhes, explica como ela é e o guia através do seu processo de instalação e ativação para a sua construção PHP. Ele fornece informações detalhadas sobre como usar esta extensão no contexto de scripts PHP, explicando a API Zorba e ilustrando-a com vários exemplos. Ele também examina algumas funções especiais do Zorba para integração com outras tecnologias da Web, como a REST e a JSON.
Antes de mais nada, uma introdução: Zorba é um processador XQuery, com uma implementação completa e totalmente compatível das especificações W3C para XQuery 1.0 e XQuery Update Facility 1.0. Ele também inclui suporte parcial para XQuery 1.1, uma implementação quase completa do XQuery Scripting Extension 1.0, e várias funções adicionais para transmissão de e-mail, geração de PDF e comentário de código. Atualmente, o Zorba está disponível para as plataformas Mac OS X, Linux®e Microsoft® Windows® como um projeto de software livre sob os termos da Licença Apache, e é suportado por várias organizações, incluindo a FLWOR Foundation e a Oracle Inc.
O suporte Zorba em PHP vem através da extensão ext/zorba do PECL, que é mantida por William Candillon, e fornece uma API orientada a objetos para acesso à biblioteca Zorba. Apesar de esta extensão estar atualmente em alpha, ela ainda permite que você faça coisas bastante interessantes, incluindo usar expressões FLWOR, trabalhar com sequencias e coletas, atualizar e manipular conjuntos de nós XML, e acessar funcionalidade específica do Zorba através de PHP. A extensão está gratuitamente disponível sob a Licença PHP.
Para iniciar com a ext/zorba, primeiro certifique-se de que as bibliotecas Zorba estão compiladas e instaladas em seu sistema. O Zorba necessita de vários outros pacotes para ser pré-instalado no sistema para uma compilação limpa, assim, antes de iniciar, certifique-se de que você possui as versões recentes do seguinte:
- libxml2
- iconv
- ICU (versão C)
- Xerces (versão C)
- GCC e utilitários de criação relacionados
Você localizará links para transferir por download todos esses pacotes, assim como o próprio Zorba (veja Recursos). As instruções de instalação variam de pacote para pacote; na maioria dos casos, você precisará seguir o ciclo de configurar-fazer-instalar padrão, mas você encontrará instruções mais específicas na documentação de cada pacote. Após instalá-los todos, transfira por download o release mais recente do Zorba (v0.9.8) e compile-o para o seu sistema. Se estiver em um sistema *NIX com GCC v4.0.1 ou melhor, precisará desses comandos:
shell> tar -xzvf zorba-0.9.8.tar.gz shell> cd zorba-0.9.8 shell> mkdir build shell> cd build shell> cmake -D CMAKE_INSTALL_PREFIX=/usr/local .. shell> make shell> make install |
No final desse processo, o Zorba deve ser instalado para a ramificação /usr/local/* do seu sistema de arquivos. Para verificar se ele foi corretamente instalado, abre o prompt de comandos, insira o seguinte comando e verifique a saída resultante:
shell> zorba -q '40+1' <?xml version="1.0" encoding="UTF-8"?> 41 |
O processo de instalação também cria uma biblioteca Zorba compartilhada, in /usr/local/lib/libzorba_simplestore.so. Como um prelúdio necessário para a instalação da extensão ext/zorba a partir do PECL, você deve criar um link para esta biblioteca, como abaixo:
shell> cd /usr/local/lib shell> ln -s libzorba_simplestore.so libzorba.so |
Agora você está pronto para instalar a extensão PECL. Se o seu ambiente incluir o comando pecl , este é um processo de etapa única:
shell> pecl install zorba-alpha |
Agora, o instalador PECL transferirá por download o código da extensão, o preparará e o compilará em um módulo PHP carregável. Figura 1 ilustra o que você deve ver durante o processo.
Figura 1. Compilando a extensão PHP do Zorba
Alternativamente, é possível transferir por download o arquivo do código de origem do PECL e compilá-lo em um módulo PHP carregável, conforme abaixo:
shell> tar -xzvf zorba-0.9.9.tgz shell> cd zorba-0.9.9 shell> phpize shell> ./configure --with-zorba_api=/usr/local/include/zorba/ shell> make shell> make install |
Nesse ponto, você deve ter um módulo PHP carregável chamado zorba_api.so no seu diretório dos módulos PHP. Ative esta extensão no arquivo de configuração php.ini, reinicie o servidor da Web, e verifique se a extensão está ativa com uma chamada rápida a phpinfo(). A Figura 2 ilustra o que você deve ver.
Figura 2. Verificando a extensão PHP do Zorba
Para terminar o processo de instalação, copie o arquivo zorba_api.php do arquivo de origem do PECL para um diretório no seu caminho de inclusão do PHP, conforme abaixo:
shell> cp zorba-0.9.9/zorba_api.php /usr/local/lib/php/ |
Vamos começar com um exemplo simples. Dê uma olhada na Lista 1, que ilustra como usar o Zorba para processar consultas XQuery de dentro de um script PHP:
Lista 1. Designando e exibindo variáveis
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar cadeia de consultas
$queryStr = <<<END
let \$message := 'She sells sea shells by the sea shore'
return
<result>{\$message}</result>
END;
$query = $zorba->compileQuery($queryStr);
// executar consulta e exibir resultado
$result = $query->execute();
echo $result;
// Limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 2 exibe a saída da Lista 1:
Lista 2. A saída da Lista 1
<?xml version="1.0" encoding="UTF-8"?>
<result>She sells sea shells by the sea shore</result>
|
A Lista 1 começa incluindo as definições de classe PHP do Zorba, e criando uma instância do armazenamento da memória com a classe InMemoryStore. Depois, o método Zorba::getInstance() é usado para inicializar uma instância do processador Zorba; esta instância serve como o ponto de acesso primário à funcionalidade XQuery do Zorba. Terminadas essas formalidades, o método compileQuery() é usado para compilar um XQuery, e o método execute() é usado para executá-lo.
E que tal o próprio XQuery? Este é um exemplo muito simples que utiliza os dois componentes FLWOR mais básicos: a cláusula let , que designa valores para variáveis e a cláusula return , que define a estrutura do conjunto de resultados do XQuery. Se estiver familiarizado com o XQuery, isto deve ser bem familiar para você: O XQuery designa um valor de cadeia a uma variável, e depois retorna-o como uma cadeia codificada em XML. Observe o uso das barras invertidas antes das variáveis XQuery dentro do docblock PHP; omiti-las produz um erro porque o PHP tenta avaliar as variáveis em vez de permitir que o Zorba as manipule.
O Zorba suporta a declaração de variáveis dentro do contexto de uma XQuery, assim como as funções matemáticas básicas. A Lista 3 demonstra esse dois aspectos:
Lista 3. Usando funções matemáticas
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar cadeia de consultas
$queryStr = <<<END
declare variable \$x := 30;
declare variable \$y := 12;
let \$r := \$x + \$y
return
<result> {\$r} </result>
END;
$query = $zorba->compileQuery($queryStr);
// executar consulta e exibir resultado
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 4 demonstra a saída da Lista 3:
Lista 4. A saída da Lista 3
<?xml version="1.0" encoding="UTF-8"?>
<result>42</result>
|
A Lista 3 usa o mesmo modelo básico da Lista 1: inicialize a classe Zorba, defina a consulta e compile e execute-a. Neste caso, a consulta primeiro declara duas variáveis e depois usa a construção let para inclui-las juntas e a construção result para retornar o resultado.
O Zorba suporta o intervalo completo de funções XQuery. Considere a Lista 5, que demonstra o uso da função concat() no contexto de uma XQuery:
Lista 5. Concatenando cadeias
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar cadeia de consultas
$queryStr = <<<END
declare variable \$x := 30;
declare variable \$y := 12;
let \$r := \$x + \$y
return
<result> {concat('The answer is: ', \$r)} </result>
END;
$query = $zorba->compileQuery($queryStr);
// executar consulta e exibir resultado
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 6 demonstra a saída:
Lista 6. A saída da Lista 5
<?xml version="1.0" encoding="UTF-8"?>
<result>The answer is: 42</result>
|
Além das cláusulas let e return, o Zorba suporta sequências, como também a cláusula for para processá-las. Para ilustrar isso na prática, considere a Lista 7:
Lista 7. Processando uma sequência
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar consulta
$queryStr = <<<END
let \$dolls := ('Echo', 'Victor', 'Sierra', 'November', 'Alpha')
return
<results>
{
for \$doll in \$dolls
return
<name>{\$doll}</name>
}
</results>
END;
$query = $zorba->compileQuery($queryStr);
// executar consulta e exibir resultado
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 7 define uma sequência de nomes, e então usa uma cláusulafor para fazer loop através desta sequência, recuperando cada nome e incluindo-a a uma coleta de nós. A Lista 7 também demonstra como é possível aninhar instruções return para controlar precisamente o conjunto de resultados gerado pela consulta.
A Lista 8 tem a saída da Lista 7:
Lista 8. A saída da Lista 7
<?xml version="1.0" encoding="UTF-8"?>
<results>
<name>Echo</name>
<name>Victor</name>
<name>Sierra</name>
<name>November</name>
<name>Alpha</name>
</results>
|
Também é possível "implodir" um sequência em uma cadeia com a função string-join() do XQuery, como na Lista 9:
Lista 9. Concatenando elementos de sequência em uma cadeia
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar consulta
$queryStr = <<<END
let \$dolls := ('Echo', 'Victor', 'Sierra', 'November', 'Alpha')
return
<results>
{string-join(\$dolls, ', ')}
</results>
END;
$query = $zorba->compileQuery($queryStr);
// executar consulta e exibir resultado
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 10 mostra a saída da Lista 9:
Lista 10. A saída da Lista 9
<?xml version="1.0" encoding="UTF-8"?>
<results>Echo, Victor, Sierra, November, Alpha</results>
|
Para gerar sequências numéricas, o Zorba suporta o operador to , que aceita o valor inicial e final de um intervalo numérico e gera uma sequência que contém todos os números dentro desse intervalo. Considere a Lista 11, que usa isso para gerar uma sequência de números entre 1 e 20, e então usa os operadores mod e eq para retornar um conjunto de resultados de números pares somente:
Lista 11. Localizando números pares
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar consulta
$queryStr = <<<END
let \$set := (1 to 20)
return
<results>
{
for \$i in \$set
where (\$i mod 2 eq 0)
return
<value> {\$i} </value>
}
</results>
END;
$query = $zorba->compileQuery($queryStr);
// executar consulta e exibir resultado
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 12 mostra a saída da Lista 11.
Lista 12. A saída da Lista 11
<?xml version="1.0" encoding="UTF-8"?>
<results>
<value>2</value>
<value>4</value>
<value>6</value>
<value>8</value>
<value>10</value>
<value>12</value>
<value>14</value>
<value>16</value>
<value>18</value>
<value>20</value>
</results>
|
A Lista 11 também demonstra o suporte do Zorba para a cláusula where do XQuery, que é comumente usada para filtrar o conjunto de resultados de saída. Mais sobre isso na seção a seguir.
Filtrando e classificando dados
Frequentemente você terá de lidar com dados XML originados em uma origem externa,—talvez um arquivo simples, talvez um serviço da Web, talvez alguma outra coisa. Para cuidar disso, a API PHP do Zorba inclui uma classe XmlDataManager, que fornece funções para carregar documentos XML externos no Zorba. A Lista 13 exibe um fragmento de um documento XML desses, que será usado como uma base para os exemplos nesta seção.
Lista 13. Um arquivo XML de amostra
<?xml version="1.0"?>
<data>
<record>
<code>ABW</code>
<name>Aruba</name>
<continent>North America</continent>
<year></year>
<population>103000</population>
<gnp>828.00</gnp>
<capital>
<name>Oranjestad</name>
<population>29034</population>
</capital>
</record>
<record>
<code>AFG</code>
<name>Afghanistan</name>
<continent>Asia</continent>
<year>1919</year>
<population>22720000</population>
<gnp>5976.00</gnp>
<capital>
<name>Kabul</name>
<population>1780000</population>
</capital>
</record>
<record>
<code>AUS</code>
<name>Australia</name>
<continent>Oceania</continent>
<year>1901</year>
<population>18886000</population>
<gnp>351182.00</gnp>
<capital>
<name>Canberra</name>
<population>322723</population>
</capital>
</record>
<record>
<code>AUT</code>
<name>Austria</name>
<continent>Europe</continent>
<year>1918</year>
<population>8091800</population>
<gnp>211860.00</gnp>
<capital>
<name>Wien</name>
<population>1608144</population>
</capital>
</record>
<record>
<code>AZE</code>
<name>Azerbaijan</name>
<continent>Asia</continent>
<year>1991</year>
<population>7734000</population>
<gnp>4127.00</gnp>
<capital>
<name>Baku</name>
<population>1787800</population>
</capital>
</record>
...
</data>
|
A Lista 14 tem um exemplo de consulta neste documento e recuperação de uma lista de todos os nomes de países nela:
Lista 14. Recuperando nomes de países
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// get XML data manager
$dm = $zorba->getXmlDataManager();
// ler documento XML externo
$dm->loadDocument('data.xml', file_get_contents('data.xml'));
// criar e compilar consulta
$queryStr = <<< END
for \$record in doc('data.xml')//record
let \$name := \$record/name/text()
let \$code := \$record/code/text()
return
<name code="{\$code}">{\$name}</name>
END;
$query = $zorba->compileQuery($queryStr);
// executar consulta e exibir resultado
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 15 exibe a saída:
Lista 15. A saída da Lista 14
<?xml version="1.0" encoding="UTF-8"?>
<name code="ABW">Aruba</name>
<name code="AFG">Afghanistan</name>
<name code="AGO">Angola</name>
<name code="AIA">Anguilla</name>
<name code="ALB">Albania</name>
<name code="AND">Andorra</name>
<name code="ANT">Netherlands Antilles</name>
<name code="ARE">United Arab Emirates</name>
<name code="ARG">Argentina</name>
<name code="ARM">Armenia</name>
<name code="ASM">American Samoa</name>
<name code="ATG">Antigua and Barbuda</name>
<name code="AUS">Australia</name>
<name code="AUT">Austria</name>
<name code="AZE">Azerbaijan</name>
<name code="BDI">Burundi</name>
<name code="BEL">Belgium</name>
<name code="BEN">Benin</name>
<name code="BFA">Burkina Faso</name>
<name code="BGD">Bangladesh</name>
...
|
A Lista 16 atualiza a Lista 14 para incluir uma cláusula where que filtra o conjunto de resultados para somente países europeus com população acima de 1.000.000, e uma cláusula order by que classifica o conjunto de resultados em ordem descendente de população:
Lista 16. Filtrando países por tamanho e local
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// obter gerenciador de dados XML
$dm = $zorba->getXmlDataManager();
// ler documento XML externo
$dm->loadDocument('data.xml', file_get_contents('data.xml'));
// criar e compilar consulta
$queryStr = <<< END
for \$record in doc('data.xml')//registrar
let \$name := \$record/name/text()
let \$code := \$record/code/text()
let \$population := \$record/population/text()
where contains(\$record/continent/text(), 'Europe')
where (xs:integer(\$population) gt 1000000)
order by \$population descending
return
<name code="{\$code}" population="{\$population}">{\$name}</name>
END;
$query = $zorba->compileQuery($queryStr);
// executar consulta e exibir resultado
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 17 exibe a saída da Lista 16:
Lista 17. A saída da Lista 16
<?xml version="1.0" encoding="UTF-8"?>
<name code="AUT" population="8091800">Austria</name>
<name code="ALB" population="3401200">Albania</name>
<name code="BEL" population="10239000">Belgium</name>
|
Além de ler e consultar XML, o Zorba também inclui funções que permitem manipular árvores de documento XML por meio da inclusão, atualização e exclusão de nós. A Lista 18 contém um arquivo XML simples que você usará por toda esta seção:
Lista 18. Um exemplo de documento XML
<?xml version='1.0'?>
<heroes>
<hero>
<name>Spiderman</name>
<alterego>Peter Parker</alterego>
</hero>
<hero>
<name>Superman</name>
<alterego>Clark Kent</alterego>
</hero>
<hero>
<name>The Flash</name>
<alterego>Wally West</alterego>
</hero>
</heroes>
|
A Lista 19 usa o Zorba para ler este arquivo e incluir uma nova entrada ao final usando uma expressão XQuery Update:
Lista 19. Incluindo nós
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// obter gerenciador de dados XML
$dm = $zorba->getXmlDataManager();
// ler documento XML externo
$dm->loadDocument('heroes.xml', file_get_contents('heroes.xml'));
// criar e compilar consulta
$queryStr = <<< END
insert node
<hero>
<name>Batman</name>
<alterego>Bruce Wayne</alterego>
</hero>
into doc('heroes.xml')//heroes
END;
$query = $zorba->compileQuery($queryStr);
$query->applyUpdates();
// agora verifique se o nó foi inserido
$queryStr = <<< END
for \$h in doc('heroes.xml')//heroes
return
<results> {\$h/hero} </results>
END;
$query = $zorba->compileQuery($queryStr);
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 20 exibe o documento XML revisado:
Lista 20. A saída da Lista 19
<?xml version="1.0" encoding="UTF-8"?>
<heroes>
<hero>
<name>Spiderman</name>
<alterego>Peter Parker</alterego>
</hero>
<hero>
<name>Superman</name>
<alterego>Clark Kent</alterego>
</hero>
<hero>
<name>The Flash</name>
<alterego>Wally West</alterego>
</hero>
<hero>
<name>Batman</name>
<alterego>Bruce Wayne</alterego>
</hero>
</heroes>
|
Também é possível excluir e substituir nós, como na Lista 21:
Lista 21. Excluindo e substituindo nós
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// obter gerenciador de dados XML
$dm = $zorba->getXmlDataManager();
// ler documento XML externo
$dm->loadDocument('heroes.xml', file_get_contents('heroes.xml'));
// criar e compilar consulta
$queryStr = <<< END
delete node doc('heroes.xml')//heroes/hero[last()],
replace node doc('heroes.xml')//heroes/hero[last()]
with
<hero>
<name>The Incredible Hulk</name>
<alterego>Bruce Banner</alterego>
</hero>
END;
$query = $zorba->compileQuery($queryStr);
$query->applyUpdates();
// agora verifique se o nó foi inserido
$queryStr = <<< END
doc('heroes.xml')
END;
$query = $zorba->compileQuery($queryStr);
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 22 tem a saída da Lista 21:
Lista 22. A saída da Lista 21
<?xml version="1.0" encoding="UTF-8"?>
<heroes>
<hero>
<name>Spiderman</name>
<alterego>Peter Parker</alterego>
</hero>
<hero>
<name>Superman</name>
<alterego>Clark Kent</alterego>
</hero>
<hero>
<name>The Incredible Hulk</name>
<alterego>Bruce Banner</alterego>
</hero>
</heroes>
|
Uma das forças do Zorba é seu suporte a uma ampla variedade de tecnologias e padrões da Web. Isso o torna adequado para uso em uma variedade de aplicativos "cola" que precisam de suporte XQuery juntamente com a capacidade de interagir com dados de origens externas variadas. Por exemplo, o Zorba vem com uma API REST completa em recursos, que permite aos desenvolvedores criar, transmitir e processar pedidos e respostas GET, POST, PUT e DELETE, tudo sem deixar o ambiente do Zorba.
Vamos ver como isso funciona usando-o com a API REST del.icio.us. Supondo que você tenha uma conta no del.icio.us, é possível fazer um pedido GET para http://user:pass@api.del.icio.us/v1/posts/recent e recuperar uma lista de indicadores recentemente incluídos. A saída é parecida com a da Lista 23:
Lista 23. Saída REST de exemplo da APIP del.icio.us
<?xml version='1.0' standalone='yes'?>
<posts tag="" user="someuser">
<post href="http://www.kernel.org/"
description="The Linux Kernel Archives"
hash="7dae6d24e3f8c6c3c3aa1b05ce5bfe94"
tag="linux kernel opensource" time="2007-12-04T09:03:25Z" />
<post href="http://www.everythingphpmysql.com/"
description="How to do Everything with PHP & MySQL - Vikram Vaswani"
hash="8c9c6572c70cb3de3fa93b87269a8d79"
tag="book development php mysql web beginner" time="2007-12-04T09:02:47Z" />
<post href="http://www.mysql-tcr.com/"
description="MySQL: The Complete Reference - Vikram Vaswani"
hash="c8d99b00cfb9a1af9d59bbc6c46848cd"
tag="mysql php book" time="2007-12-04T09:02:21Z" />
...
</posts>
|
Se você fizer isso com o Zorba, poderá processar ainda mais o XML retornado usando o XQuery. Considere a Lista 24, que ilustra por meio da execução do mesmo pedido GET através do Zorba, a filtragem do conjunto de resultados para incluir somente aqueles resultados marcados como 'book', e enviando os resultados por meio de sistema de mensagens para um formato diferente do original:
Lista 24. Executando um pedido GET
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar consulta
$queryStr = <<< END
import module namespace zorba-rest =
"http://www.zorba-xquery.com/zorba/rest-functions";
for \$post in
zorba-rest:get("http://user:pass@api.del.icio.us/v1/posts/recent")//posts/post
where contains(\$post/@tag, 'book')
return
<result>
<href> {string(\$post/@href)} </href>
<description> {string(\$post/@description)} </description>
<tags> {string(\$post/@tag)} </tags>
</result>
END;
$query = $zorba->compileQuery($queryStr);
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 25 exibe o resultado:
Lista 25. A saída da Lista 24
<?xml version="1.0" encoding="UTF-8"?>
<result>
<href>http://www.everythingphpmysql.com/</href>
<description>How to do Everything with PHP & MySQL - Vikram Vaswani</description>
<tags>book development php mysql web beginner</tags>
</result>
<result>
<href>http://www.mysql-tcr.com/</href>
<description>MySQL: The Complete Reference - Vikram Vaswani</description>
<tags>mysql php book</tags>
</result>
|
Em uma linha similar, o Zorba também oferece as funções put(), post(), head() e delete() , que correspondem aos comandos PUT, POST, HEAD, e
DELETE HTTP respectivamente. Para incluir parâmetros de pedido nesses comandos, especifique-os no segundo argumento, como na Lista 26:
Lista 26. Executando um pedido POST
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar consulta
$queryStr = <<< END
import module namespace zorba-rest =
"http://www.zorba-xquery.com/zorba/rest-functions";
zorba-rest:post(
'http://server/admin/login',
<payload>
<part name='username'>john</part>
<part name='password'>guessme</part>
</payload>
)
END;
$query = $zorba->compileQuery($queryStr);
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A resposta de uma transação HTTP é automaticamente codificada em um pacote de resultados XML pelo Zorba. A Lista 27 exibe um exemplo:
Lista 27. Um pacote de resposta HTTP codificada
<?xml version="1.0" encoding="UTF-8"?>
<zorba-rest:result xmlns:zorba-rest="http://www.zorba-xquery.com/zorba/rest-functions">
<zorba-rest:status-code>200</zorba-rest:status-code>
<zorba-rest:headers>
<zorba-rest:header zorba-rest:name="Date">Fri, 16 Oct 2009 12:20:15 GMT
</zorba-rest:header>
<zorba-rest:header zorba-rest:name="Server">
Apache/2.2.11 (Win32) PHP/5.2.6
</zorba-rest:header>
<zorba-rest:header zorba-rest:name="X-Powered-By">PHP/5.2.6
</zorba-rest:header>
<zorba-rest:header zorba-rest:name="Content-Length">22
</zorba-rest:header>
<zorba-rest:header zorba-rest:name="Content-Type">text/html
</zorba-rest:header>
</zorba-rest:headers>
<zorba-rest:payload>
<result>1</result>
</zorba-rest:payload>
</zorba-rest:result>
|
Por que parar com REST? O Zorba também inclui funções para analisar dados codificados em JSON e retorná-los em um formato XML. A Lista 28 tem um exemplo do uso da função json() do Zorba para retornar uma representação XML de um pacote JSON:
Lista 28. Analisando JSON no XML
<?php
// configurar dados JSON
$json = '{
"books": [{
"title":"Phantom Prey",
"author":"John Sandford",
"price":"7.99"
}, {
"title":"A Most Wanted Man",
"author":"John le Carre",
"price":"8.99"
}, {
"title":"Her Fearful Symmetry",
"author":"Audrey Niffenegger",
"price":"17.99"
}, {
"title":"The Watchman",
"author":"Robert Crais",
"price":"7.99"
}, {
"title":"Beach Babylon",
"author":"Imogen Edward-Jones",
"price":"12.99"
}]}';
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar consulta
$queryStr = <<< END
import module namespace json =
"http://www.zorba-xquery.com/zorba/json-functions";
json:parse('{$json}')
END;
$query = $zorba->compileQuery($queryStr);
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 29 exibe a saída da Lista 28:
Lista 29. A saída da Lista 28
<?xml version="1.0" encoding="UTF-8"?>
<json type="object">
<pair name="books" type="array">
<item type="object">
<pair name="title" type="string">Phantom Prey</pair>
<pair name="author" type="string">John Sandford</pair>
<pair name="price" type="string">7.99</pair>
</item>
<item type="object">
<pair name="title" type="string">A Most Wanted Man</pair>
<pair name="author" type="string">John le Carre</pair>
<pair name="price" type="string">8.99</pair>
</item>
<item type="object">
<pair name="title" type="string">Her Fearful Symmetry</pair>
<pair name="author" type="string">Audrey Niffenegger</pair>
<pair name="price" type="string">17.99</pair>
</item>
<item type="object">
<pair name="title" type="string">The Watchman</pair>
<pair name="author" type="string">Robert Crais</pair>
<pair name="price" type="string">7.99</pair>
</item>
<item type="object">
<pair name="title" type="string">Beach Babylon</pair>
<pair name="author" type="string">Imogen Edward-Jones</pair>
<pair name="price" type="string">12.99</pair>
</item>
</pair>
</json>
|
Isto é extremamente útil porque permite aplicar o poder do XQuery para rapidamente extrair as informações necessárias de um pacote de resultados codificado em JSON. A Lista 30 expande a Lista 28, ilustrando isto em ação com um XQuery para retornar os títulos de todos os livros abaixo de US$10.00:
Lista 30. Analisando e filtrando JSON com XQuery
<?php
// configurar dados JSON
$json = '{
"books": [{
"title":"Phantom Prey",
"author":"John Sandford",
"price":"7.99"
}, {
"title":"A Most Wanted Man",
"author":"John le Carre",
"price":"8.99"
}, {
"title":"Her Fearful Symmetry",
"author":"Audrey Niffenegger",
"price":"17.99"
}, {
"title":"The Watchman",
"author":"Robert Crais",
"price":"7.99"
}, {
"title":"Beach Babylon",
"author":"Imogen Edward-Jones",
"price":"12.99"
}]}';
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar consulta
$queryStr = <<< END
import module namespace json =
"http://www.zorba-xquery.com/zorba/json-functions";
let \$x := json:parse('{$json}')
for \$i in \$x//item
where (xs:decimal(\$i/pair[@name='price']/text()) lt 10.00)
return
<result> {\$i/pair[@name='title']/text()} </result>
END;
$query = $zorba->compileQuery($queryStr);
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 31 exibe a saída revisada:
Lista 31. A saída da Lista 30
<?xml version="1.0" encoding="UTF-8"?>
<result>Phantom Prey</result>
<result>A Most Wanted Man</result>
<result>The Watchman</result>
|
É possível usar algumas outras funções de utilitário específico do Zorba dentro do ambiente PHP. Por exemplo, a Lista 32 demonstra as funções random() e uuid() , que produz um número inteiro aleatório e identificador exclusivo, respectivamente:
Lista 32. Gerando identificadores exclusivos e aleatórios
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// criar e compilar consulta
$queryStr = <<< END
import module namespace util =
"http://www.zorba-xquery.com/zorba/util-functions";
let \$uuid := util:uuid()
let \$random := util:random()
return
<results>
<uuid> {\$uuid} </uuid>
<random> {\$random} </random>
</results>
END;
$query = $zorba->compileQuery($queryStr);
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 33 exibe a saída da Lista 32:
Lista 33. A saída da Lista 32
<?xml version="1.0" encoding="UTF-8"?>
<results>
<uuid>87f0cf54-ba41-11de-a89c-9300a64ac3cd</uuid>
<random>71869107</random>
</results>
|
Outro exemplo é a função serialize-to-string() , que aceita uma coleta de nós e os serializa em uma única cadeia. A Lista 34 tem um exemplo:
Lista 34. Serializando nós
<?php
// incluir API Zorba
require_once 'zorba_api.php';
// criar instância Zorba na memória
$ms = InMemoryStore::getInstance();
$zorba = Zorba::getInstance($ms);
try {
// obter gerenciador de dados XML
$dm = $zorba->getXmlDataManager();
// ler documento XML externo
$dm->loadDocument('heroes.xml', file_get_contents('heroes.xml'));
// criar e compilar consulta
$queryStr = <<< END
import module namespace util =
"http://www.zorba-xquery.com/zorba/util-functions";
let \$xml := doc('heroes.xml')//heroes/hero[1]
let \$str:= util:serialize-to-string(\$xml)
return
<result> {\$str} </result>
END;
$query = $zorba->compileQuery($queryStr);
$result = $query->execute();
echo $result;
// limpar
$query->destroy();
$zorba->shutdown();
InMemoryStore::shutdown($ms);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
A Lista 35 exibe a saída da Lista 34:
Lista 35. A saída da Lista 34
<?xml version="1.0" encoding="UTF-8"?>
<result>
<hero>
<name>Spiderman</name>
<alterego>Peter Parker</alterego>
</hero>
</result>
|
Também é possível usar as funções integradas do Zorba para enviar e-mail e criar documentos PDF. Leia mais sobre essas funções na documentação do Zorba.
É basicamente isso neste artigo. Nas últimas páginas, eu dei um curso intensivo sobre como incluir suporte XQuery com força industrial à sua construção PHP como processador XQuery do Zorba. Além de guiá-lo pelo processo de instalação, eu mostrei como usar o Zorba para processar expressões FLWOR básicas, iterar sobre sequências, e ler dados XML de origens externas. Eu também espliquei rapidamente o suporte XQuery Update do Zorba, mostrando como incluir, atualizar e excluir dinamicamente nós de um documento XML, e mostrei como explorar o suporte USP do Zorba—para tecnologias de "cola" comuns como REST e JSON—para a máxima vantagem na construção de aplicativos da Web.
Espero que tudo isso tenha servido para estimular seu apetite, e eu o encorajo a dar uma chance ao Zorba da próxima vez que construir um aplicativo PHP/XML/XQuery. Boa sorte e feliz codificação!
Aprender
- Expressões XQuery e FLWOR (este link reside fora de ibm.com): Aprenda o básico por meio de exemplo.
- XPath, XQuery (este link reside fora de ibm.com) e XQuery Update (este link reside fora de ibm.com): Revise as especificações no Web site do W3C (este link reside fora de ibm.com).
- O Web site oficial do Zorba (este link reside fora de ibm.com) e a documentação do Zorba (este link reside fora de ibm.com): Aprenda mais sobre esse processador XQuery de propósito geral.
- Funcionalidade REST (este link reside fora de ibm.com) e suporte JSON (este link reside fora de ibm.com) no Zorba: Leia mais sobre o suporte do Zorba na documentação on-line (este link reside fora de ibm.com).
- Uma demo ao vivo do Zorba (este link reside fora de ibm.com): Experimente algumas consultas de amostra com esta demo.
- o wiki do Zorba (este link reside fora de ibm.com) e o rastreador de erros do Zorba (este link reside fora de ibm.com): Participe da comunidade do Zorba.
- A área XML no developerWorks: Obtenha os recursos necessários para melhorar suas habilidades na arena XML.
- Certificação XML da IBM: Descubra como é possível se tornar um Desenvolvedor Certificado IBM em XML e tecnologias relacionadas.
- Biblioteca técnica XML: veja a Zona XML do developerWorks para uma ampla gama de artigos e dicas técnicos, tutoriais, padrões e Redbooks da IBM.
- Eventos e webcasts técnicos do developerWorks: mantenha-se atualizado com a tecnologia nessas sessões.
- podcasts do developerWorks: ouça a entrevistas e discussões interessantes para desenvolvedores de software.
Obter produtos e tecnologias
- O processador XQuery do Zorba (este link reside fora de ibm.com): faça o download deste processador XQuery de propósito geral para usar em muitas plataformas.
- A extensão PHP do Zorba (este link reside fora de ibm.com): Obtenha um wrapper da biblioteca Zorba que permita aos desenvolvedores em PHP usarem o XQuery.
- o pacote libxml2 (este link reside fora de ibm.com): faça o download do analisador XML C e do kit de ferramentas desenvolvido para o projeto Gnome.
- A biblioteca de conversão Unicode de iconv (este link reside fora de ibm.com): faça o download desta ferramenta para conversão entre representação de cadeia interna (Unicode) e representação de cadeia externa (uma codificação tradicional) durante E/S.
- As bibliotecas Unicode ICU (este link reside fora de ibm.com): faça o download deste conjunto de bibliotecas C/C++ e Java para Unicode e suporte à globalização em seus aplicativos de software.
- o analisador Xerces XML (este link reside fora de ibm.com): faça o download deste analisador XML de validação e forneça aos seus aplicativos a habilidade de ler e gravar dados XML.
- Versões de avaliação de produto IBM: faça o download ou explore as avaliações on-line no IBM SOA Sandbox e coloque suas mãos em ferramentas de desenvolvimento de aplicativos e produtos de middleware do DB2®, Lotus®, Rational®, Tivoli®e WebSphere®.
Discutir
- Fóruns de discussão da zona XML: Participe de qualquer uma das várias discussões relacionadas a XML.
- blogs do developerWorks: Confira esses blogs e envolva-se na comunidade do developerWorks.

Vikram Vaswani é o fundador e Presidente da Melonfire (este link reside fora de ibm.com), uma empresa de serviços de consultoria com conhecimento especial sobre ferramentas e tecnologias de software livre. Ele também é o autor dos livros PHP Programming Solutions (este link reside fora de ibm.com) e PHP: A Beginners Guide (este link reside fora de ibm.com).