Skip to content

13. Exercício IMPOTS com XML

Neste exercício, já estudado inúmeras vezes, o servidor devolve os resultados ao cliente sob a forma de um fluxo XML.

13.1. O servidor (impots_05B_web)

O serviço web de cálculo de impostos descrito anteriormente tem uma arquitetura em camadas:

No exemplo anterior, o serviço web enviava aos seus clientes uma das duas linhas seguintes:

<erreur>message d'erreur</erreur>
<impot>montant de l'impôt</impot>

Este não é um documento XML bem formado, uma vez que não possui uma baliza raiz. O novo serviço web enviará a sua resposta com o seguinte formato:

<reponse><erreur>message d'erreur</erreur></reponse>

ou

<reponse><impot>montant de l'impôt</impot></reponse>

Em ambos os casos, a resposta é um documento XML válido que pode ser processado pelo módulo [simpleXML].

No esquema de três camadas, apenas a camada [web] deve ser alterada. O seu código [impots_05B_web] passa a ser o seguinte:


<?php

// camada de negócio
require_once "impots_05_metier.php";

// gestão de erros
ini_set("display_errors", "off");

// cabeçalho UTF-8
header("Content-Type: text/plain; charset=utf-8");

// ------------------------------------------------------------------------------
// o serviço web das finanças
// definição de constantes
$HOTE = "localhost";
$PORT = 3306;
$BASE = "dbimpots";
$USER = "root";
$PWD = "";
// os dados necessários para o cálculo do imposto foram inseridos na tabela mysqL $TABLE
//, pertencente à base de dados $BASE. A tabela tem a seguinte estrutura
// limites decimal(10,2), coeffR decimal(6,2), coeffN decimal(10,2)
// os parâmetros dos contribuintes (estado civil, número de filhos, salário anual)
// são enviados pelo cliente no formato params=estado civil, número de filhos, salário anual
// os resultados (estado civil, número de filhos, salário anual, imposto a pagar) são devolvidos ao cliente
// na forma <imposto>imposto</imposto>
// ou no formato <erro>erro</erro>, se os parâmetros forem inválidos
// recupera-se a camada [métier] na sessão
session_start();
if (!isset($_SESSION['metier'])) {
// instanciação da camada [dao] e da camada [métier]
  try {
    $_SESSION['metier'] = new ImpotsMetier(new ImpotsDaoWithMySQL($HOTE, $PORT, $BASE, $USER, $PWD));
  } catch (ImpotsException $ie) {
    print "<reponse><erreur>Erreur : " . utf8_encode($ie->getMessage() . "</erreur></reponse>");
    exit;
  }
}
$metier = $_SESSION['metier'];

// recupera-se a linha enviada pelo cliente
$params = utf8_encode(htmlspecialchars(strtolower(trim($_POST['params']))));
//print "parâmetros recebidos --> $params\n";
$items = explode(",", $params);
// só deve haver 3 parâmetros
if (count($items) != 3) {
  print "<reponse><erreur>[$params] : nombre de paramètres invalides</erreur></reponse>\n";
  exit;
}//if
// o primeiro parâmetro (estado civil) deve ser sim/não
$marié = trim($items[0]);
if ($marié != "oui" and $marié != "non") {
  print "<reponse><erreur>[$params] : 1er paramètre invalide</erreur></reponse>\n";
  exit;
}//se
// o segundo parâmetro (número de filhos) deve ser um número inteiro
if (!preg_match("/^\s*(\d+)\s*$/", $items[1], $champs)) {
  print "<reponse><erreur>[$params] : 2ième paramètre invalide</erreur></reponse>\n";
  exit;
}//se
$enfants = $champs[1];
// o terceiro parâmetro (salário) deve ser um número inteiro
if (!preg_match("/^\s*(\d+)\s*$/", $items[2], $champs)) {
  print "<reponse><erreur>[$params] : 3ième paramètre invalide</erreur></reponse>\n";
  exit;
}//se
$salaire = $champs[1];
// calcula-se o imposto
$impôt = $metier->calculerImpot($marié, $enfants, $salaire);
// retorna-se o resultado
print "<reponse><impot>$impôt</impot></reponse>\n";
// fim
exit;

O formato da resposta do serviço web é alterado nas linhas 35, 47, 53, 58, 64 e 71.

13.2. O cliente (client_impots_05b_web)

O cliente é alterado para ter em conta o novo formato da resposta. Utiliza-se [simpleXML] para processar a resposta:


<?php

// cliente de impostos
// gestão de erros
ini_set("display_errors", "off");

// ---------------------------------------------------------------------------------
// uma classe de funções utilitárias
class Utilitaires {
...
}

// main -----------------------------------------------------
// definição de constantes
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
// dados do servidor
$HOTE = "localhost";
$PORT = 80;
$urlServeur = "/exemples-web/impots_05B_web.php";

...
exit;

function calculerImpot($HOTE, $PORT, $urlServeur, &$cookie, $params) {
  // liga o cliente a ($HOTE,$PORT,$urlServeur)
// envia o cookie $cookie se este não estiver vazio. $cookie é passado por referência
// envia $params para o servidor
// processa a linha do resultado
...
  // leitura da linha do resultado
  $ligne = fgets($connexion, 1000);
  // encerra-se a ligação
  fclose($connexion);
  // cálculo do resultado
  $xml = new SimpleXMLElement($ligne);
  $erreur = isset($xml->erreur) ? $xml->erreur : "";
  $impôt = isset($xml->impot) ? $xml->impot : "";
  // retorno
  return array($erreur, $impôt);
}
  • linha 32: a resposta do servidor é lida. Trata-se de um documento XML.
  • linha 36: é criado um objeto SimpleXML a partir do documento XML recebido.
  • linha 37: a eventual mensagem de erro
  • linha 38: o eventual montante do imposto