Formatting data in XML with PHP

Notice: Article only available in Spanish!

Ahora que ya he explicado cómo crear una clase en php para leer datos de una base de datos, y que también conocemos las bases del lenguaje XML, vamos a crear una clase para formatear estos datos en XML. De este modo, podremos compartir datos entre distintos tipos de aplicaciones, sin necesidad de tener acceso al servidor de bases de datos más que en una de ellas: la pasarela de datos.

Una vez formateamos en correcto XML, podemos ofrecer un documento como XML puro para aplicaciones externas que quieran utilizar nuestros datos, o un RSS estándar para que nuestros visitantes sincronicen las noticias del sitio; podemos también ofrecer un servicio SOAP para aplicaciones que no sólo precisen nuestros datos sino también funciones y servicios avanzados; o podemos simplemente adjuntar una hoja de estilos xls y mostrar nuestro documento en un navegador, como lo haríamos con xhtml y css. Bastante útil, ¿no?

Vamos allá: para la clase necesitaremos algunas propiedades que permitan almacenar el contenido, así­ como un constructor, un método para cargar datos (en arrays multidimensionales), y otro método para recuperarlos (como arrays). También necesitaremos un método toString(), o toXML más propiamente hablando para formatear directamente los datos a XML. Comencemos con el prototipo de la clase:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class xml 
{
  //
  var $content;
  var $xml_version;
  var $xml_encoding;
  var $data_label;
  var $item_label;
  //
 
  /** 
   * constructor; loads some default values
   */
  public function xml() {}
 
  /** 
   * Gets data to show in a two dimmensional array and stores it internally
   */
  function setContent($data = NULL) {}
 
  /** 
   * Returns content from a matrix
   * @return the content
   */
  function getContent() {}
 
  /** 
   * Shows as a text string values in XML format
   * @return XML formatted data
   */
  function toString() {}
 
  /** 
   * Returns XML header
   * @return XML header
   */
  function header(){}
 
}

Para la matriz de datos, esperamos un array asociativo, donde cada elemento $content[] tenga el valor asociado al índice, correspondiente al nombre del campo de la tabla. Por ejemplo, en nuestra tabla ‘superheroes’ con los campos ‘id’, ‘name’, ‘special_powers’, la matriz que la clase espera obtener es del tipo:

1
2
3
4
5
6
7
$content[0]['id']             = "101";
$content[0]['name']            = "spider man";
$content[0]['special_powers'] = "crawling in the walls";
$content[1]['id']             = "102";
$content[1]['name']           = "mosquito man";
$content[1]['special_powers'] = "run away from spider man";
....

y el formato XMLque esperamos de salida es

1
2
3
4
5
<data>
  <item id="101" name="spider man" special_powers="crawling in the walls"></item>
  <item id="102" name="mosquito man" special_powers="run away from spider man"></item>
   ...
</data>

podemos elegir varios formatos para el XMLde salida, en concreto usaremos el anterior, sin embargo podríamos haber utilizado un formato anidado del tipo

1
2
3
4
5
6
7
8
9
10
11
12
<data>
  <item>
    <id>101</id>
    <name>spider man</name>
    <special_powers>crawling in the walls</special_powers>
  </item>
  <item>
    <id>102</id>
    <name>mosquito man</name>
    <special_powers>run away from spider man</special_powers>
  </item>
</data>

Elijo el primer formato por sencillez, y porque siendo yo quien voy a leer de él en otras aplicaciones, no tengo que preocuparme por la compatibilidad. Si vamos a integrar nuestra pasarela XML con otros servicios o aplicaciones web, quizá nos interese saber primero qué formato espera encontrar dicha aplicación para ofrecerle datos que le resulten legibles.

Por otra parte, si se usa la clase dbhandler para proporcionar los datos en arrays a esta clase, debe modificarse la función readTable para que quede así­

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
 * retrieves data from the selected fields of a certain table
 * @param table to read from
 * @param fields to be retrieved
 */
function readTable($table,$fields)
{
  //variables
  $resultsArray = array();
 
  //fields
  $fieldsList = "";
  foreach($fields as $key=>$value)
  {
    $fieldsList .= $value . ",";
  }
 
  //remove last comma
  $fieldsList = substr($fieldsList,0,strlen($fieldsList)-1);
 
  //consulta
  $this->query = "SELECT " . $fieldsList . " FROM " . $table;
  $this->resultset = @mysql_query($this->query,$this->identifier);
  $this->results = @mysql_num_rows($this->resultset);
 
  if ( $this->results > 0)
  {
    $i = 0;
    while ($result = mysql_fetch_array($this->resultset))
    {
      foreach($fields as $key=>$index)
      {
        $resultsArray[$i][$index] = $result[$index] ; //return results in a matrix
        // each result has an index called as the column name in their table
      }
      $i++;
    }
  }
 
  return($resultsArray);
 
}

Sólo queda rellenar el prototipo con el contenido de las funciones:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* 
 * class to format data as XML
 * @author Jorge Albaladejo Pomares [correo@jorgealbaladejo.com]
 * @license Creative Commons License http://creativecommons.org/licenses/by-sa/3.0/
 */
//
class xml 
{
  //
  var $content;
  var $xml_version;
  var $xml_encoding;
  var $data_label;
  var $item_label;
  //
 
  /** 
   * constructor; loads some default data
   */
  public function xml() 
  {
    $this->content       = array();
    $this->xml_version   = "1.0";
    $this->xml_encoding  = "ISO-8859-1";
    $this->data_label    = "datos";
    $this->item_label    = "item";
  }
 
  /** 
   * Gets data to show in a two dimmensional array
   * and stores it internally
   */
  function setContent($data = NULL) 
  {
    if ($data != NULL) 
    {
      $this->content = $data;
    }
  }
 
  /** 
   * Gets data to show in a two dimensional array
   * and stores it internally
   */
  function getContent() 
  {
    return ($this->content);
  }
 
  /** 
   * Shows as a text string values in XML format
   * @return XML formatted data
   */
  function toString() 
  {
    if ($this->content != NULL) 
    {
      $return  = "";
      $return .= $this->header();
      $return .= "<".$this->data_label.">\n";
 
      //for each element from the matrix, there is a nested matrix with data from mysql.
      foreach ($this->content as $result)
      {
        $return .= "\t<".$this->item_label;
        foreach( $result as $key => $value ) 
        {
          $return .= " " . $key . "=\"" . $value ."\"";
        }
        $return .= "/>\n";
      }
      $return .= "<!--".$this-->data_label.">";
    }
 
    return ($return);
  }
 
  /** 
   * Returns XML header
   * @return XML header
   */
  function header()
  {
    return ("xml_version."\" encoding=\"".$this->xml_encoding."\"?>\n");
  }

Y un script que utilice estas dos clases (dbhandler y xml) para mostrar datos de una base de datos nos quedaría tan sencillo como ésto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * script connect to a database and read tables using XML
 * @author Jorge Albaladejo Pomares [correo@jorgealbaladejo.com]
 * @license Creative Commons License http://creativecommons.org/licenses/by-sa/3.0/
 */
 
//main classes
include('class.dbhandler.php');
include('class.xml.php');
 
//main script
$db     = new dbhandler('john_smith','h01y_GRail','pastafarian_food','localhost');
$fields   = array('id', 'name', 'special_powers');
$results = $db->readTable('superheroes',$fields);
 
//got data, show them as XML
$xml = new xml();
$xml->setContent($results);
header('Content-Type: text/xml');
echo $xml->toString();
$db->disconnect();

2 thoughts on “Formatting data in XML with PHP

  1. Howdy there,this is Dalton Medeiros,just identified your web-site on google and i must say this blog is great.may I quote some of the writing found in your website to my local students?i’m not sure and what you think?anyway,Thanks!

  2. Hi Dalton, I’m glad to hear that. Well, I wouldn’t say that any of my articles is ‘academic’ material but rather some handy solutions for given problems. Anyway, feel free to share them with your students, it would be interesting to know how these examples of code serve for teaching :)

    Any further feedback on the result would be most than welcome,

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *