Avançar para a área de conteúdo

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Todas as informações enviadas são seguras.

  • Fechar [x]

Construindo Aplicativos desenvolvidos com XQuery com PHP e Zorba

Inclua suporte XQuery no PHP com o Zorba

Vikram Vaswani, Founder, Melonfire
Photo of Vikram Vaswani
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).

Resumo:  Zorba é um processador XQuery de software livre, robusto e compatível com os padrões. A extensão Zorba em PHP fornece uma API para funções Zorba de dentro do PHP e, dessa forma, permite que os desenvolvedores incluam processamento XQuery sofisticado em seus aplicativos PHP/XML. Examine a API PHP do Zorba em detalhes, e com usá-la para uma variedade de propósitos.

Data:  18/Nov/2009
Nível:  Intermediário
Atividade:  3976 visualizações
Comentários:  


Introdução

Acrônimos frequentemente usados

  • API: Interface de programa de aplicativo
  • DOM: Modelo de Objeto do Documento
  • HTML: Linguagem de Marcação de Hipertexto
  • HTTP: Protocolo de Transferência de Hipertexto
  • JSON: Notação de Objeto JavaScript
  • PDF: Formato de Documento Móvel
  • REST: Transferência de Estado Representativo
  • SAX: API Simples para XML
  • USP: Proposição de Vendas Exclusiva
  • W3CL: Consórcio World Wide Web
  • WDDX: Troca de Dados Distribuídos da Web
  • XML: Linguagem de Marcação Extensível
  • XML-DAS: Serviço de Arquivamento de Dados XML
  • XSL: Linguagem de Folha de Estilo Extensível

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.


Instalando o Zorba

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
Captura de tela de mensagens durante a compilação da 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
Captura de tela da resposta phpinfo() que verifica se o módulo Zorba_api é ativo

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/


Entendendo o uso básico

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>


Processando sequências

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>


Manipulando coletas de nós

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>


Usando funções REST

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>


Usando funções JSON

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.


Conclusão

É 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!


Recursos

Aprender

Obter produtos e tecnologias

Discutir

Sobre o autor

Photo of Vikram Vaswani

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).

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=447878
ArticleTitle=Construindo Aplicativos desenvolvidos com XQuery com PHP e Zorba
publish-date=11182009
author1-email=vikram.melonfire@gmail.com
author1-email-cc=

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).