Skip to content

13. IMPOTS Ejercicio con XML

En este ejercicio, que ya hemos estudiado muchas veces, el servidor devuelve los resultados al cliente en forma de flujo XML.

13.1. El servidor (impots_05B_web)

El servicio web de cálculo de impuestos escrito anteriormente tiene una arquitectura en capas:

En el ejemplo anterior, el servicio web envió una de las dos líneas siguientes a sus clientes:

<error>error message</error>
<tax>tax amount</tax>

No se trata de un documento XML bien formado porque carece de etiqueta raíz. El nuevo servicio web enviará su respuesta en el siguiente formato:

<response><error>error message</error></response>

o

<response><tax>tax amount</tax></response>

En ambos casos, la respuesta es un documento XML bien formado que puede ser procesado por el módulo [simpleXML].

En la arquitectura de tres niveles, sólo es necesario modificar la capa [web]. Su código [impots_05B_web] pasa a ser el siguiente:


1. <?php
2. 
3. // business layer
4. require_once "impots_05_business.php";
5. 
6. // error handling
7. ini_set("display_errors", "off");
8. 
9. // UTF-8 header
10. header("Content-Type: text/plain; charset=utf-8");
11. 
12. // ------------------------------------------------------------------------------
13. // the tax web service
14. // definition of constants
15. $HOST = "localhost";
16. $PORT = 3306;
17. $DATABASE = "dbimpots";
18. $USER = "root";
19. $PWD = "";
20. // The data needed to calculate the tax has been placed in the MySQL table $TABLE
21. // belonging to the $BASE database. The table has the following structure
22. // limits decimal(10,2), coeffR decimal(6,2), coeffN decimal(10,2)
23. // the parameters for taxable individuals (marital status, number of children, annual salary)
24. // are sent by the client in the form params=marital status, number of children, annual salary
25. // the results (marital status, number of children, annual salary, tax due) are returned to the client
26. // in the form <tax>tax</tax>
27. // or in the form <error>error</error>, if the parameters are invalid
28. // retrieve the [business] layer from the session
29. session_start();
30. if (!isset($_SESSION['business'])) {
31. // instantiate the [dao] layer and the [business] layer
32.   try {
33.     $_SESSION['metier'] = new ImpotsMetier(new ImpotsDaoWithMySQL($HOST, $PORT, $BASE, $USER, $PWD));
34.   } catch (ImpotsException $ie) {
35.     print "<response><error>Error: " . utf8_encode($ie->getMessage() . "</error></response>");
36.     exit;
37.   }
38. }
39. $job = $_SESSION['job'];
40. 
41. // retrieve the line sent by the client
42. $params = utf8_encode(htmlspecialchars(strtolower(trim($_POST['params']))));
43. //print "parameters received --> $params\n";
44. $items = explode(",", $params);
45. // there must be exactly 3 parameters
46. if (count($items) != 3) {
47.   print "<response><error>[$params]: number of invalid parameters</error></response>\n";
48.   exit;
49. }//if
50. // the first parameter (marital status) must be yes/no
51. $married = trim($items[0]);
52. if ($married != "yes" and $married != "no") {
53.   print "<response><error>[$params]: Invalid first parameter</error></response>\n";
54.   exit;
55. }//if
56. // the second parameter (number of children) must be an integer
57. if (!preg_match("/^\s*(\d+)\s*$/", $items[1], $fields)) {
58.   print "<response><error>[$params]: Invalid second parameter</error></response>\n";
59.   exit;
60. }//if
61. $children = $fields[1];
62. // the third parameter (salary) must be an integer
63. if (!preg_match("/^\s*(\d+)\s*$/", $items[2], $fields)) {
64.   print "<response><error>[$params]: Invalid third parameter</error></response>\n";
65.   exit;
66. }//if
67. $salary = $fields[1];
68. // calculate the tax
69. $tax = $occupation->calculateTax($married, $children, $salary);
70. // return the result
71. print "<response><tax>$tax</tax></response>\n";
72. // end
73. exit;

El formato de la respuesta del servicio web se modifica en las líneas 35, 47, 53, 58, 64 y 71.

13.2. El cliente (client_impots_05b_web)

El cliente se modifica para tener en cuenta el nuevo formato de respuesta. Utilizamos [simpleXML] para procesarlo:


1. <?php
2. 
3. // tax client
4. // error handling
5. ini_set("display_errors", "off");
6. 
7. // ---------------------------------------------------------------------------------
8. // a class of utility functions
9. class Utilities {
10. ...
11. }
12. 
13. // main -----------------------------------------------------
14. // definition of constants
15. $DATA = "data.txt";
16. $RESULTS = "results.txt";
17. // server data
18. $HOST = "localhost";
19. $PORT = 80;
20. $serverUrl = "/web-examples/taxes_05B_web.php";
21. 
22. ...
23. exit;
24. 
25. function calculateTax($HOST, $PORT, $serverUrl, &$cookie, $params) {
26.   // connects the client to ($HOST, $PORT, $serverUrl)
27. // sends the $cookie if it is not empty. $cookie is passed by reference
28. // sends $params to the server
29. // processes the result line
30. ...
31.   // read the result line
32.   $line = fgets($connection, 1000);
33.   // close the connection
34.   fclose($connection);
35.   // calculate result
36.   $xml = new SimpleXMLElement($line);
37.   $error = isset($xml->error) ? $xml->error : "";
38.   $tax = isset($xml->tax) ? $xml->tax : "";
39.   // return
40.   return array($error, $tax);
41. }
  • línea 32: se lee la respuesta del servidor. Se trata de un documento XML.
  • línea 36: Se construye un objeto SimpleXML a partir del documento XML recibido.
  • línea 37: cualquier mensaje de error
  • línea 38: importe del impuesto, en su caso