viernes, 6 de julio de 2012

La línea following de XPath

La línea following de XPath contiene todos los nodos que empiezan después del nodo de contexto.

El analizador procesa los documento XML de la misma manera que un lector lee un documento en la cultura occidental, o sea, de izquierda a derecha y de arriba a abajo. Este extremo es importante para predecir qué nodos serán seleccionados por la línea axis que apliquemos.

En siguiente ejemplo, al igual que otros ejemplos de las entradas relativas a las líneas XPath utilizaremos el documento XML de la entrada "La línea descendant de XPath"

Por ello, en el ejemplo que sigue, si señalamos como nodo de contexto el X/B/R/B, el conjunto de nodos dado la línea following, (más la clase de nodo node()) estará constituido por todos los nodos del árbol que estén a la derecha y considerados de arriba a abajo, en el presente caso serán cinco nodos.

Ejemplo nº1, la línea following de XPath

Hoja de transformación:

          <?xml version="1.0" encoding="UTF-8" ?>

<!-- New document created with EditiX at Thu Jul 05 18:01:36 BST 2012 -->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="/">
  <xsl:copy-of select="X/B/R/B/following::node()"/>
 </xsl:template>
</xsl:stylesheet>

Salida:


<C>
   <F>
      <Z/>
      <N/>
      <M/>
   </F>
</C>

<F>
   <Z/>
   <N/>
   <M/>
</F>

<Z/>
<N/>
<M/>
        

En la siguiente representación del árbol XML en el que he aplicado la hoja de transformación pueden ver el nodo de contexto y los nodos que constituyen el resultado de la línea following

jueves, 5 de julio de 2012

La línea descendant-or-self de XPath

Esta línea contiene el propio nodo de contexto y todos los descendientes de ese nodo.

En el siguiente ejemplo el fichero de entrada es el mismo que el de la entrada "La línea descendant de XPath"

Ejemplo nº1, la línea descendant-or-self de XPath

Hoja de transformación:

          <?xml version="1.0" encoding="UTF-8" ?>

<!-- New document created with EditiX at Thu Jul 05 18:01:36 BST 2012 -->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="/">
  <xsl:copy-of select="X/B/G/descendant-or-self::node()"/>
 </xsl:template>
</xsl:stylesheet>

Salida:

<G> <E/> <G/> <Y/> </G> <E/> <G/> <Y/>

En el siguiente esquema puedes ver el resultado de aplicar al árbol XMl la línea descendant-or-self. No cambié el color del nodo de contexto porque este nodo también resulta elegido por la línea.

miércoles, 4 de julio de 2012

La línea descendant de XPath

Dado un nodo de contexto, la línea descendant selecciona los hijos de ese nodo y además los nietos, los biznietos, etc.

La línea descendant no selecciona los atributos de los nodos y tampoco la nombre de espacio.

Para la selección utilizo tanto pasos de localización simplificados como sin simplificar. La notación no simplificada es más intuitiva, pero es más pesada.

Documento XML de ejemplo

          <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Wed Jul 04 18:40:54 BST 2012 -->

<X>
 <A>
  <F>
   <T/>
   <K/>
   <P/>
   <Q/>
  </F>
  <F>
   <E/>
  </F>
 </A>
 <B>
  <G>
   <E/>
   <G/>
   <Y/>
  </G>
  <J>
   <E/>
  </J>
  <R>
   <A/>
   <w/>
   <Q/>
   <B/>
  </R>
 </B>
 <C>
  <F>
   <Z/>
   <N/>
   <M/>
  </F>
 </C>
</X>
        

En el siguiente ejemplo debes notar que el nodo de contexto es doble, ya que hay dos nodos con la misma etiqueta, lo cual no es muy académico, pero pese a ello el analizador lo resuelve; por tanto, fíjate que el resultado da como resultado la descendencia de dos nodos.

Ejemplo nº1, línea descendant de XPath

Hoja de transformación:

          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="/">
  <xsl:copy-of select="X/A/F/descendant::node()"/>
 </xsl:template>
</xsl:stylesheet>

Salida:

<T/> <K/> <P/> <Q/> <E/>

Recordemos que existe una notación simplificada de XPath. En el siguiente ejemplo simplificamos mediante (//) la línea descendant. Nota que el resultado es la descendencia de todos los nodos con etiqueta F,

Ejemplo nº2, notación simplificada de la línea descendant

Hoja de transformación:

          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="/">
  <xsl:copy-of select="//F/descendant::node()"/>
 </xsl:template>
</xsl:styleshee>

Salida:

<T/> <K/> <P/> <Q/> <E/> <Z/> <N/> <M/>

lunes, 2 de julio de 2012

Nodo test en XPath

El nodo test es uno de los componente del paso de localización XPath y junto con la línea va definir cuáles son los nodos que vamos a coger del árbol XML que analizamos.
Además de tener una línea XPath, cada paso de localización tiene un nodo test. El nodo test tiene dos maneras excluyentes de elegir los nodos: por el nombre del nodo (el nombre de la etiqueta XML) o por la clase de nodo.

Las clases de nodos son las siguientes:

  • comment()
  • node()
  • processing-instruction()
  • text()

Recordemos que utilizamos una línea XPath dentro de un paso de localización para indicar al analizador que nos estamos refiriendo a un determinado número de nodos del árbol XML que tratamos. Dicho de otra manera: cada una de las líneas supone un conjunto de nodos que están predefinidos en la especificación y que siempre son los mismos tomoando como referencia el nodo de contexto.

Por ejemplo, si escribimos el paso de localización

child::isla

usamos una línea (la línea child) y un el nombre de nodo "isla", que corresponderá a una etiqueta del documento XML.


Ejemplo nº1 Nodo test con nombre de nodo y con clase de nodo

Entrada:

<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Mon Jul 02 17:41:45 BST 2012 -->

<isla nombre="La Palma" capital="Santa Cruz de la Palma">
 <gentilicio_masculino>
 palmero
 <!--Por supuesto, el gentilicio femenino será palmera-->
 </gentilicio_masculino>
 <superficie>708,32</superficie>
 <sitio nombre="Tazacorte">
  <gentilicio_masculino>bagañete</gentilicio_masculino>
  <superficie>11,36</superficie>
 </sitio>
 <sitio nombre="Villa de Mazo">
  <gentilicio_masculino>mazuco</gentilicio_masculino>
  <superficie>71,17</superficie>
 </sitio>
 <sitio nombre="Santa Cruz de la Palma">
  <gentilicio_masculino>santacrucero</gentilicio_masculino>
  <superficie> 43,38</superficie>
 </sitio>
</isla>

Hoja de transformación:

<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Sun Jun 17 18:55:04 BST 2012 -->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="/">
  <!--Utilizamos en el paso de localización final como nodo test el nombre del elemento-->
  <xsl:element name="gentilicio_1">
   <xsl:value-of select="child::isla/child::gentilicio_masculino"/>
  </xsl:element>
  <!--Utilizamos en el paso de localización final como nodo test el nombre de la clase de nodo texto.
  En este caso el nodo gentilicio_masculino tiene dos hijos: un nodo texto y un nodo comentario-->
  <xsl:element name="gentilicio_2">
   <xsl:value-of select="child::isla/child::gentilicio_masculino/child::text()"/>
  </xsl:element>
  <!--Utilizamos en el paso de localización final como nodo test el nombre de la clase de nodo comentario.-->
  <xsl:element name="comentario">
   <xsl:value-of select="child::isla/child::gentilicio_masculino/child::comment()"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

Salida:

<gentilicio_1>palmero</gentilicio_1>

<gentilicio_2>palmero</gentilicio_2>

<comentario>Por supuesto, el gentilicio femenino será palmera</comentario>
        

domingo, 1 de julio de 2012

Los pasos de localización

Los pasos de localización (location steps) te permiten navegar dentro de la jerarquía del documento XML y, de esa manera, seleccionar un conjunto de nodos que están relacionados en alguna forma con el nodo de contexto.

Un paso de navegación se compone de tres partes: una línea o eje, un nodo test y un predicado, que es opcional.

Aquí se produce una confusión porque la expresión de los pasos de localización se pueden simplificar mediante una sintaxis abreviada, por tanto, la persona que empieza en XPath se podrá encontrar expresiones que, en principio, no entienda. Aquí, en esta entrada, voy a proponer la notación no simplificada, la cual, a pesar de que se usa menos, es más fácil de entender al ser más intuitiva.

Sin perjuicio de que añada al blog una entrada que recoja esta notación simplificada, la puedes encontrar en decenas de sitios de la red, casi siempre en inglés.

Por tanto, el salto de localización tal como

axis::nodetest[predicado]
se compone de tres partes:
Axis
Especifica una relación entre el nodo de contexto y otros nodos del árbol. Las líneas están predifinidas de antemano en la especificación XPath. Ejemplos son las líneas child, parent, ancestror, etc. Todas ellas siguen el modelo de la familia: hijos, padres, hermanos, antepasados, etc. Para tener noción de cuales son estas líneas busca en cualquier manual de XPaht, aunque tengo intención de añadir una entrada con las líneas XPath. También las puedes localizar fácilmente en la red. En algunas páginas se incluyen instructivos gráficos para saber que nodos se seleccionan cuando se utilizan cada una de las líneas.
Nodetest.
Especifica los tipos de nodos o el nombre de los nodos que serán seleccionados inicialmente por el salto de localización. El axis y el nodetest de unen para crear una sintaxis del tipo: "dame los hijos de los nodos llamados cliente", o "dame los nodos que contengan texto que sean descendientes del nodo de contexto", etc.
Predicado
Supone una condición opcional del tipo "where" usada en SQL. Viene a significar un refinamiento en la búsqueda que inicialmente han dado las dos expresiones anteriores. El predicado es opcional, es decir, no hará falta usarlo si las expresiones axis y nodetest ya han definido el conjunto de nodos del árbol XML que buscamos. El predicado se encierra entre corchetes([])

El siguiente ejemplo no contiene predicado que según dije al comienzo de la entrada es el tercer elemento del paso de localización y es opcional.

En la cláusula "select" de la hoja de transformación contiene un paso que utiliza en el nodetest varios nombres de elementos que se encuentran jerarquizados entre ellos.

El la cláusula "value-of" de la hoja de transformación se utiliza en el nodetest una clase de nodo, en este caso text().


Ejemplo nº1 Ejemplo de pasos de localización

Entrada:

          <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Sun Jul 01 22:32:22 BST 2012 -->

<!--Varios pueblos y ciudades de cada una de las Islas Canarias, con división entre islas occidentales y orientales -->

<canarias>
 <islas_occidentales>
  <isla nombre="La Palma" capital="Santa Cruz de la Palma">
   <gentilicio_masculino>palmero</gentilicio_masculino>
   <superficie>708,32</superficie>
   <sitio nombre="Tazacorte">
    <gentilicio_masculino>bagañete</gentilicio_masculino>
    <superficie>11,36</superficie>
   </sitio>
   <sitio nombre="Villa de Mazo">
    <gentilicio_masculino>mazuco</gentilicio_masculino>
    <superficie>71,17</superficie>
   </sitio>
   <sitio nombre="Santa Cruz de la Palma">
    <gentilicio_masculino>santacrucero</gentilicio_masculino>
    <superficie> 43,38</superficie>
   </sitio>
  </isla>
  <isla nombre="El Hierro" capital="Valverde de El Hierro">
   <gentilicio_masculino>herreño</gentilicio_masculino>
   <superficie>268,71</superficie>
   <sitio nombre="El Pinar">
    <gentilicio_masculino>piñero</gentilicio_masculino>
    <superficie>84,95</superficie>
   </sitio>
   <sitio nombre="Valverde de El Hierro">
    <gentilicio_masculino>valverdecino</gentilicio_masculino>
    <superficie>103,65</superficie>
   </sitio>
  </isla>
  <isla nombre="La Gomera" capital="San Sebastián de la Gomera">
   <gentilicio_masculino>gomero</gentilicio_masculino>
   <superficie>369,76</superficie>
   <sitio nombre="Alajeró">
    <gentilicio_masculino>lagartero</gentilicio_masculino>
    <superficie>49,42</superficie>
   </sitio>
   <sitio nombre="San Sebastián de la Gomera">
    <gentilicio_masculino/>
    <superficie>113,59</superficie>
   </sitio>
  </isla>
  <isla nombre="Tenerife" capital="Santa Cruz de Tenerife">
   <gentilicio_masculino>tinerfeño</gentilicio_masculino>
   <superficie>2034,38</superficie>
   <sitio nombre="Güímar">
    <gentilicio_masculino>güimarero</gentilicio_masculino>
    <superficie>102,93</superficie>
   </sitio>
   <sitio nombre="La Orotava">
    <gentilicio_masculino>orotavense o villero</gentilicio_masculino>
    <superficie>207,31</superficie>
   </sitio>
   <sitio nombre="Santa Cruz de Tenerife">
    <gentilicio_masculino>santacrucero o chicharrero</gentilicio_masculino>
    <superficie>150,56</superficie>
   </sitio>
  </isla>
 </islas_occidentales>
 <islas_orientales>
  <isla nombre="Lanzarote" capital="Arrecife de Lanzarote">
   <gentilicio_masculino>lanzaroteño</gentilicio_masculino>
   <superficie>845,94</superficie>
   <sitio nombre="Haría">
    <gentilicio_masculino>hariano</gentilicio_masculino>
    <superficie>106,59</superficie>
   </sitio>
   <sitio nombre="Arrecife de Lanzarote">
   <gentilicio_masculino>arrecifeño</gentilicio_masculino>
   <superficie>22,72</superficie>
   </sitio>
  </isla>
  <isla nombre="Fuerteventura" capital="Puerto del Rosario">
   <gentilicio_masculino>majorero</gentilicio_masculino>
   <superficie>1659,74</superficie>
   <sitio nombre="Betancuria">
    <gentilicio_masculino>bentacuriano</gentilicio_masculino>
    <superficie>103,64</superficie>
   </sitio>
   <sitio nombre="Puerto del  Rosario">
    <gentilicio_masculino>puertense</gentilicio_masculino>
    <superficie>289,95</superficie>
   </sitio>
  </isla>
  <isla nombre="Gran Canaria" capital="Las Palmas de Gran Canaria">
   <gentilicio_masculino>grancanario o, coloquialmente, canarión</gentilicio_masculino>
   <superficie>1560,1</superficie>
   <sitio nombre="La Aldea de San Nicolás">
    <gentilicio_masculino>aldeano</gentilicio_masculino>
    <superficie>123,58</superficie>
   </sitio>
   <sitio nombre="Las Palmas de Gran Canaria">
    <gentilicio_masculino>de las Palmas</gentilicio_masculino>
    <superficie>100,55 </superficie>
   </sitio>
  </isla>
 </islas_orientales>
</canarias>

Hoja de transformación:

<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Sun Jun 17 18:55:04 BST 2012 -->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
 <xsl:template match="/">
  <xsl:apply-templates select="child::canarias/child::islas_occidentales/child::isla/child::gentilicio_masculino"/>
 </xsl:template>
 <xsl:template match="child::isla">
  <xsl:element name="gentilicio">
   <xsl:value-of select="child::text()"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

Salida:

<gentilicio>palmero</gentilicio>
<gentilicio>herreño</gentilicio>
<gentilicio>gomero</gentilicio>
<gentilicio>tinerfeño</gentilicio>
        

domingo, 24 de junio de 2012

Expresión Xpath y contexto

Una expresión Xpath siempre será evaluada por el analizador con respecto a un contexto, de ahí la importancia del concepto.
El contexto nos indica dónde está posicionado el analizador en un momento dado dentro del documento XML.
El contexto contiene los siguientes elementos:

  • Un nodo, que se llama nodo contextual.
  • Un par de enteros positivos no nulos que señalan la posición contextual y el tamaño contextual. 
  1. La posición contextual señala la posición del nodo contextual dentro del documento XML.
  2. El tamaño contextual es el número de nodos que contiene el nodo contextual, a dicha cantidad hay que sumarle una unidad para tener en cuenta el propio nodo.
  • Un conjunto de asignaciones para variables destinadas al tratamiento de valores de variables que provengan el exterior del nodo y que tengan consecuencias en el interior nodo contextual.
  • Una biblioteca de funciones que pudieran actuar en el nodo
  • El conjunto de declaraciones de espacios de nombres que pudieran ser aplicados a la expresión

El nodo de contexto se debe proporcionar al analizador de manera previa a la expresión Xpath, aunque se le puede dar de manera implícita en el momento de proporcionarle la expresión.

Proporcionamos al analizador un nodo de contexto cuando le proporcionamos una localización absoluta dentro del documento. La localización absoluta siempre empieza en el nodo raíz del documento.

Por ejemplo, dado el documento XML catalogo.xml. La expresión de Xquery:

doc(catalogo.xml)/catalogo/producto/nombre
, proporciona al analizador un nodo de contexto que es el nodo "nombre"

Para quienes empiezan en XML es muy difícil de comprender la noción de contexto y nodo de contexto, pero es crucial lograrlo porque, de otra manera, es imposible avanzar sin tropiezos y pérdida de tiempo por el mundo del Xquery y el Xslt.


miércoles, 13 de junio de 2012

Tipos de nodos XML

A fin de comprender la semántica Xpath, primero es necesario entender modelo de datos XPath, es decir, cómo XPath trata un documento XML. El modelo de datos XPath representa cada documento XML como un árbol de nodos. Del mismo modo podemos imaginar un modelo basado en la relaciones familiares, esto es, padres, hijos, descendientes, ascendientes, etc.

Cada nodo puede ser de uno de estos tipos siguientes:

Raíz

El nodo raíz es un nodo virtual que no corresponde a ningún componente en el documento XML. Más bien se trata del lugar donde comienza el árbol XML. El nodo raíz puede tener hijos comentarios para cada comentario que esté fuera del elemento documento, hijos instrucciones de procesamiento, la declaración XML . El nodo raíz no tiene padre.

Este elemento también es conocido como el elemento documento.

Todos los documentos XML deben de contener una etiqueta raíz que, al igual que cualquier otra del documento constará de apertura y cierre. Dentro de la raíz se desarrollará el contenido del documento XML.

Ejemplo nº1 Desarrollo del contenido del nodo raíz

         <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Wed Jun 13 16:55:21 BST 2012 -->

 <!DOCTYPE example [<!ENTITY copy "©">]>
 <?php $a = 'Instrucción de proceso'; ?>
  
 
<Elemento_raíz attribute="t12">
 <?php echo 'otra instrucción de proceso'; ?>
 <contenido/>
    texto opcional
 </Elemento_raíz> 
        

Elemento

Un nodo elemento corresponde a un elemento XML y se etiqueta con una etiqueta de apertura y otra de cierre. Cada elemento siempre tendrá un padre, salvo que sea el nodo raíz y puede tener hijos de tipo de elemento, comentarios, instrucciones de procesamiento y el texto. Los atributos y espacios de nombres asociados con el elemento no son hijos del nodo elemento. El valor de cadena de un nodo elemento es el texto contenido entre las etiquetas de inicio y cierre del elemento con exclusión de todas las etiquetas, comentarios e instrucciones de procesamiento.

Atributo

Un nodo de atributo corresponde a una cualidad o propiedad del elemento al que califica. Su padre es el nodo de elemento que contiene el atributo (sin embargo, el atributo no es un hijo de su padre!). El valor de cadena de un nodo atributo es el valor del atributo.

Ejemplo nº2 Ejemplo de documento con atributos en sus elementos

        <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Wed Jun 13 17:09:14 BST 2012 -->

<atributos>
<!--Representamos mediante atributos tres bolas: una mía, otra tuya y otra suya. La primera es roja, la segunda amarilla y la tercera verde-->
 <bolas>
  <bola color="rojo" situación="primera">
  mía
  </bola>
  <bola color="amarilla" situación="segunda">
  tuya
  </bola>
  <bola color="verde" situación="tercera">
  suya
  </bola>
 </bolas>
</atributos>  
        

Texto

Un nodo de texto es una cadena de texto situada dentro de las etiquetas, los comentarios o las instrucciones de procesamiento. Tiene un nodo padre, pero carece de hijos. Su valor de cadena es el texto del nodo.

Ejemplo nº3 Nodo de texto

        <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Wed Jun 13 17:09:14 BST 2012 -->


<xml>
 El lenguaje de marcas extensible, XML, es un lenguaje de etiquetas que define un conjunto de reglas para codificar documentos de forma que puedan ser entendidos tanto por personas como por ordenadores.
</xml>  
        

Espacio de nombres

Un nodo de espacio de nombres representa un espacio de nombres. Al igual que los nodos de atributo, los nodos de espacio de nombres tiene un padre, pero no son hijos de sus padres. El valor de cadena de un nodo de espacio de nombres es el URI de espacio de nombres. Los espacios de nombre se utilizan para impedir las confusiones del analizador con respecto a nombres de etiquetas de elementos que sean iguales.

Comentario

Un nodo de comentario contiene un comentario sobre cuestiones que interesan al redactor del documento y suelen referirse a aclaraciones o guías de uso. Tiene nodo padre pero no tienen nodos hijo. El valor de cadena de un nodo comentario es el contenido del comentario.

Ejemplo nº4 Comentarios

         <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Wed Jun 13 17:09:14 BST 2012 -->

<comentario>
<!--Representamos mediante atriburos tres bolas: una mía, otra tuya y otra suya: la primera es roja, la segunda es amarilla y la tercera es verde-->
<!--Este es comentario. Suele aclarar aspectos del documento para ayudar a su comprensión-->
</comentario> 
        

Instrucciones de procesamiento

Un nodo instrucción de procesamiento representa una instrucción de procesamiento. Tiene nodo padre pero no tiene nodos hijo. El valor de cadena de un nodo instrucción de procesamiento es el contenido de la instrucción.

En el ejemplo nº1 hay un ejemplo de instrucción de procesamiento

domingo, 10 de junio de 2012

Los espacios de nombre en XML

Los espacios de nombre proporcionan un método para evitar los conflictos que se pudieran producir entre los nombres de los elementos de un documento XML.

Los conflictos de nombre en XML

En XML los nombres de los elementos están definidos por el usuario. Dados varios documentos XML desarrollados por distintos autores, si los mezclamos en un único documento con cierta probabilidad se producirán conflictos entre los nombres de los distintos elementos.

Los conflictos se pueden producir, por ejemplo, entre palabras que tienen distinto significado, dependiendo del contexto en el que se utilicen; o también fruto de la casualidad si se da el caso de que dos autores utilicen los mismos nombres de etiquetas para cuestiones distintas y que no tienen nada que ver entre sí.

La página de w3schools.com propone un ejemplo basado en el distinto significado de la palabra “table” si es utilizada formando parte del lenguaje de etiquetas HTML o si se usa en un documento XML con el significado de un mueble.

Evidentemente la etiqueta “table” tiene un significado distinto según nos refiramos a su sentido en la primera rama del árbol o a la segunda rama del árbol XML.

Ejemplo nº1 Ejemplo de conflicto de nombres en un documento XML

          <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Fri Jun 08 17:52:21 BST 2012 -->

<!--Ejemplo de conflicto de nombres en un documento XML-->

<conflicto>
 <table>
  <tr>
   <td>ciruelas</td>
   <td>plátanos</td>
  </tr>
 </table>
 <table>
  <clase>Pino envejecido</clase>
  <medidas>
   <largo>151</largo>
   <ancho>75</ancho>
  </medidas>
 </table>
</conflicto>
        

Resolución de los conflictos de nombre

Los posibles conflictos que se pudieran producir entre los nombres elementos de un documento XML se pueden soslayar mediante la utilización de sufijos que distingan entre los nombres situados en distintas partes del documento.

En realidad, lo que conseguimos mediante la utilización de prefijos en los nombres de las etiquetas estriba en conseguir dos nombre distintos.

Ejemplo nº2 Ejemplo de una posible solución del nombres en un documento XML

          <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Fri Jun 08 17:52:21 BST 2012 -->

<!--Ejemplo de una posible solución del nombres en un documento XML-->

<conflicto>
 <h:table>
  <h:tr>
   <h:td>ciruelas</h:td>
   <h:td>plátanos</h:td>
  </h:tr>
 </h:table>
 <f:table>
  <f:clase>Pino envejecido</f:clase>
  <f:medidas>
   <f:largo>151</f:largo>
   <f:ancho>75</f:ancho>
  </f:medidas>
 </f:table>
</conflicto>
        

Los espacios de nombre y el atributo xmlns

Cuando se utilizan los prefijos en XML debemos definir el espacio de nombres, esa operación se lleva a cabo mediante el atributo xmlns en la etiqueta inicial de un elemento. De esa manera el procesador del documento conoce que los nombres que son descendientes de ese elemento forman un grupo con una sintaxis especial o distinta de otros grupos de elementos.

Lo explico con el símil del árbol XML: cuando colocamos un atributo xmlns en una rama del árbol XML el parser sabe que toda esa rama (todos los descendientes del primer elemento) tiene un especialidad respecto al nombre de sus elementos. Cuando un espacio de nombres se define para un elemento, todos los elementos secundarios con el mismo prefijo se asocian con el mismo espacio de nombre

La declaración de espacio de nombres tiene la siguiente sintaxis. xmlns: prefijo = " URI ".

Los espacios de nombres se pueden declarar en el primer elemento de la rama donde se utilizan o en el elemento raíz de XML.

El nombre de espacio es un identificador de recursos uniforme (URI). Normalmente el URI que se elige describe un recurso que está bajo el control del autor del documento, aunque eso no sucede siempre. Los autores, sobre todo si son empresas, suelen elegir la dirección de su página web donde, quizá, se da alguna información acerca del espacio de nombre utilizado pero, como digo, eso no es obligatorio.

Nota: El URI de espacio no es utilizado por el analizador para buscar información, simplemente lo trata como una cadena de documento y se limita a tomar nota de que los descendientes de ese elemento tienen una notación especial.

El propósito es dar el espacio de nombres un nombre único. Sin embargo, a menudo las empresa utilizan el espacio de nombres como un puntero a una página web que contiene información sobre el espacio de nombres.

Ejemplo nº3 Sintaxis de la declaración del atributo xmlns

          <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Fri Jun 08 17:52:21 BST 2012 -->

<!--Sintaxis de la declaración del atributo xmlns-->

<conflicto>
 <h:table xmlns:h="http://www.w3.org/TR/html4/">
  <h:tr>
   <h:td>ciruelas</h:td>
   <h:td>plátanos</h:td>
  </h:tr>
 </table>
 <f:table xmlns:f="http://metamorfosisytransformaciones.blogspot.com.es/">
  <f:clase>Pino envejecido</f:clase>
  <f:medidas>
   <f:largo>151</f:largo>
   <f:ancho>75</f:ancho>
  </f:medidas>
 </f:table>
</conflicto>
        

La declaración también se puede hacer en la raíz del documento

Ejemplo nº3 (bis) Sintaxis de la declaración del atributo xmlns en la raíz

         <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Fri Jun 08 17:52:21 BST 2012 -->

<!--Sintaxis de la declaración del atributo xmlns en la raiz del documento-->

<conflicto
xmlns:h="http://www.w3.org/TR/html4/"
xmlns:f="http://metamorfosisytransformaciones.blogspot.com.es/">
 <h:table >
  <h:tr>
   <h:td>ciruelas</h:td>
   <h:td>plátanos</h:td>
  </h:tr>
 </table>
 <f:table>
  <f:clase>Pino envejecido</f:clase>
  <f:medidas>
   <f:largo>151</f:largo>
   <f:ancho>75</f:ancho>
  </f:medidas>
 </f:table>
</conflicto>
        

Los espacios de nombre por defecto

La definición de un espacio de nombres por defecto situada en el elemento raíz de la rama a la que afecta nos permite evitar la utilización prefijos en todos los elementos secundarios. Tiene la siguiente sintaxis:

xmlns="namespaceURI"

Ejemplo nº4 Ejemplo de espacio de nombre por defecto

          <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Fri Jun 08 17:52:21 BST 2012 -->

<!--Ejemplo de espacio de nombre por defecto-->

<conflicto>
 <table xmlns="http://www.w3.org/TR/html4/">
  <tr>
   <td>ciruelas</td>
   <td>plátanos</td>
  </tr>
 </table>
 <table xmlns="http://metamorfosisytransformaciones.blogspot.com.es/">
  <clase>Pino envejecido</clase>
  <medidas>
   <largo>151</largo>
   <ancho>75</ancho>
  </medidas>
 </table>
</conflicto>
        

Espacios de nombres en el uso real

La definición de un espacio de nombres por defecto situada en el elemento raíz de la rama a la que afecta nos permite evitar la utilización prefijos en todos los elementos secundarios. Tiene la siguiente sintaxis:

xmlns="namespaceURI"

XSLT es un lenguaje XML que puede ser utilizado para transformar documentos XML en otros formatos, como HTML.

En el documento XSLT a continuación, puede ver que la mayoría de las etiquetas son las etiquetas HTML.

En el documento XSLT a continuación, puede ver que la mayoría de las etiquetas son las etiquetas HTML.

El documento Xslt corresponde a la entrada de este blog "Las listas simples en Xslt"

Tabla nº5 Uso del espacio de nombre por defecto en una hoja de transformación XSLT

<?xml version="1.0" encoding="UTF-8"?>
    <!-- New document created with EditiX at Tue Apr 17 00:09:53 BST 2012 -->
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="islas">
    <xsl:apply-templates select="isla"/>
    </xsl:template>
    <xsl:template match="isla">
    <xsl:value-of select="position(  )"/>
    <xsl:text>. </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>
    </xsl:text>
    </xsl:template>
    </xsl:stylesheet>

jueves, 7 de junio de 2012

Las entidades de nombre en XML

Las entidades de nombre, también conocidas como entidades internas en la especificación XML, constituyen las más comunes de las entidades de este lenguaje estructurado. Todo el mundo piensa en la entidades de nombre cuando se habla de las entidades de XML, aún así hay más tipos de entidades que puedes consultar en algún manual.

Para entender mejor cual puede ser el papel de las entidades dentro de nuestro documento XML, podemos imaginarlas como una especie de macros que expanden al momento de procesarlas y facilitan la edición del documento. Las entidades de nombre pueden ser de dos clases: externas e internas.

En esencia, definir una entidad de nombre consiste en asociar un nombre con un valor, sea en la declaración del documento o sea en un fichero externo. Cuando el procesador comienza a leer el documento guarda en memoria las relaciones que hemos establecido y luego, ya dentro del documento, lleva a cabo una sustitución cada vez que encuentre el nombre que hemos dado a nuestra entidad de nombre.

La utilidad más apropiada sería evitar las repeticiones durante la redacción de nuestro documento XML. Viene a ser una búsqueda con reemplazamiento, instrucción que se halla presente en todos los procesadores de texto.

La declaración de la entidad dentro del texto del documento encerrando el nombre entre los signos (&) y (;) de la siguiente manera: &nombre de la entidad;

En las declaraciones de nombre internas la declaración se lleva a cabo dentro de la etiqueta de tu documento.

Las entidades internas pueden hacer referencia a otras entidades internas, pero si creamos un bucle (cuando una entidad llama a otra y esta otra vuelve a llamar a la primera) se producirá un error

En las entidades de nombre internas la declaración se lleva a cabo dentro de la etiqueta del documento, por el contrario, en las entidades de nombre externas la declaración tiene lugar en un fichero externo al documento que tratamos, aunque, por supuesto, la llamada tiene lugar en el propio documento. El fichero externo puede contener datos binarios o texto

Si el entidad de nombre externa hace referencia a un texto, éste será insertado en el lugar donde indiquemos dentro del documento y será parseado junto con él. En cambio si los datos externos son binarios no se parsearán y el procesador se limitará a tomar nota. Los datos binarios se usan para introducir en el documento XML figuras y otros formatos que no pueden ser procesados por el parser XML

Ejemplo nº 1 Utilización de una entidad de nombre interna en XML
        <?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Wed Jun 06 19:41:13 BST 2012 -->

<!DOCTYPE nota [
  <!ENTITY socio "Javier Rodríguez">
  <!ENTITY título-conferencia "Capitalización bancaria en un entorno de crísis europea">
  <!ENTITY fecha "18 de Junio de 2012">
  <!ENTITY nombre-salón "Cañadas del Teide">
  <!ENTITY nombre-hotel "Bahía del Duque">
  <!ENTITY dirección-hotel "Adeje">
]>
 
<nota>
 <entrada>
  Estimado asociado: D. &socio;
 </entrada>
 <cuerpo>
  Le recordamos que la conferencia "&título-conferencia;" se celebrará el próximo día &fecha; en el salón &nombre-salón; del hotel &nombre-hotel;, situado en la localidad de &dirección-hotel; 
 </cuerpo>
 <pie>
  Un saludo
 </pie>
</nota>

Vamos a poner ahora un ejemplo de utilización de una entidad de nombre externa en XML para obtener datos de una base de datos XML situada en la red.

Ejemplo nº 2 Utilización de una entidad de nombre externa en XML
        <?xml version="1.0" standalone="no" ?>
<!DOCTYPE descanso-dominical [
  <!ENTITY descanso SYSTEM "http://musicbrainz.org/ws/2/release/6a59e1fc-f8ba-408c-90d1-ce2693b4caee?inc=artist-credits%2Blabels%2Bdiscids%2Brecordings">
]>

<!--Mediante una entidad de nombre externa se llama al contenido del álbum "Descanso dominical" del grupo Mecano,
utilizando la base de datos de Musicbrainz-->

<!--Puedes utilizar Internet Explorer para abrir el documento XML resultante, en Chrome no funciona-->

<descanso_dominical>
&descanso;
</descanso_dominical>

Las entidades de carácter XML

Los caracteres especiales son caracteres que no forman parte de los conjuntos de caracteres de la norma ISO 8859-1, o ASCII (Latin-1). Caracteres ASCII y Latin-1 se puede representan mediante un octeto (byte) de la información y se pueden mostrar en casi todos los editores y lectores en la mayoría de los sistemas informáticos. Los caracteres especiales van más allá de este conjunto y se representan mejor como caracteres Unicode.

Las entidades de carácter permiten especificar cualquier carácter unicode en formato decimal (&#nnn;), donde nnn es el valor decimal del carácter o en formato hexadecimal(&#xhhh;), donde hhh es el valo hexadecimal del carácter.

Si lo quisieramos representar como una entidad de carácter, tendriamos que tipear (&#65); en representación decimal o (&#x41;) en representación hexadecimal.

miércoles, 6 de junio de 2012

Las entidades predefinidas

En algunos manuales las entidades predefinidas se conocen como entities references, lo cual a mi da que se puede traducir como referencias de entidades. Las entidades predefinidas XML forman parte de la familia de la entidades XML. Recordemos que las entidades XML pueden ser:

  • Entidades de caracteres
  • Entidades de nombre
  • Entidades externas
  • Entidades de parámetro
  • Entidades predefinidas

La entidades predefinidas sirven para escapar determinados signos y que no interfieran con el parser al procesar el documentos. Es obvio que parcer puede tomar por una apertura de etiqueta el signo de ángulo abierto a la derecha: “<”, por ello se escapa mediante el código: (<) Por tanto, la entidades predefinidas se utilizan para escapar determinados caracteres que pueden producir conflictos al ser introducidos en la síntaxis XML.

Para la representación de contenido, tal como he dicho más arriba, XML proporciona una serie de construcciones sintácticas que comienzan con un signo (&) y terminan con un punto y coma (;).

Las referencias de caracteres también proporcionan una forma de insertar caracteres Unicode mediante un número que apunta al punto de código Unicode deseado.

Elementos de código pueden ser identificados utilizando decimal o hexadecimal.

Son las siguientes, extraidas de wikipedia:
Name Character Unicode code point (decimal) Standard Description
quot " U+0022 (34) XML 1.0 double quotation mark
amp & U+0026 (38) XML 1.0 ampersand
apos ' U+0027 (39) XML 1.0 apostrophe (= apostrophe-quote)
lt < U+003C (60) XML 1.0 less-than sign
gt > U+003E (62) XML 1.0 greater-than sign

El siguiente documento XML es válido. En él he sustituido los ángulos por sus correspondientes entidad predefinida XML. Para no olvidarme de las principales digo una regla nemotécnica que es "el loto del gato", frase cuyas vocales con la adición de (&) al principio y (;) al final te dan las entidades.


Table 2. Enumeración de las frutas que están en una estantería
<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Tue Jun 05 18:18:29 BST 2012 -->

<frutas_de_la_estantería>
 <fruta>Naranjas</fruta>
 <fruta>Melones</fruta>
 <fruta>Sandías</fruta>
 <fruta>Limones</fruta>
 <fruta>Peras</fruta> 
 <fruta>Ciruelas</fruta>
</frutas_de_la_estantería>

El tema no es baladí, porque si estuviese escribiendo el texto anterior, que es un ejemplo a mostrar en mi blog, utilizando para ello un editor XML, no habría manera de escribirlo porque el parseador nunca te daría el texto como válido al producirse un error en su validación y nunca podrías guardarlo. Se produce un error porque interpreta los signos en ángulo como aperturas y cierres de etiquetas sin que yo esté editando ninguna de ellas.

martes, 5 de junio de 2012

Las etiquetas XML

Las etiquetas XML

El lenguaje de marcas XML se caracteriza por ser un sistema de información estructurado, o sea, el lenguaje se conforma mediante una estructura. El entramado estructural se consigue mediante el uso de las etiquetas: unas que son específica o previstas por la norma del lenguaje y otras creadas por el usuario aunque estas últimas también habrán de ser construidas respetando las normas de la especificación. Las etiquetas vienen a ser las piezas que unidas dan forma a una estructura.

Sin embargo, el símil de la construcción estructural que he referido antes no ha ganado adeptos entre los usuarios del lenguaje XML. Los teóricos prefieren hablar de árbol de información o de familia compuesta de padres hijos, nietos, sobrinos, etc.. Sea una metáfora u otra, se trata de entender que estamos ante una manera de configurar la información.

En el fondo se trata de la vieja teoría de la comunicación y su codificación. Para transmitir una información antes habrá de codificarse para luego ser fácilmente recuperada por el el receptor. El lenguaje XML es un sistema de codificación de la información, igual que lo pueda ser la codificación mediante bases de datos relacionales. De hecho, en los últimos años estos dos sistemas de codificación y almacenación han tendido hacia el mismo punto, de forma que la sintaxis de sus respectivos lenguajes de decodificación se parecen mucho, ya que una expresión SQL recuerda mucho a una expresión XQuery. Por otro lado los programas de tratamiento de información como MYSQL contienen códigos para transformar un sistema en otro

Por otro lado hoy se habla con normalidad de bases de datos XML sin que nadie se sorprenda, por supuesto, dejando a un lado la diferencia de sus arquitecturas. No hace falta un gran salto en el vacío para considerar que en un docuemento XML se puede equiparar a una tabla de una base datos relacional. Por el mismo motivo, las líneas de tablas de bases de datos se pueden igualar a las etiquetas XML. De hecho el lenguaje XML puede representan en una línea todos los registros de una línea de una tabla relacional, lo cual se lleva a cabo mediante la utilización de los atributos de las etiquetas que ahora trataremos. Esta sorprende propiedad no debe ser nunca perdida de vista por todo aquel que se adentre en este lenguaje porque facilita la comprensión de muchos aspectos de los documentos XML. La dificultad de la comprensión de la estructuración que permite el lenguaje XML procede de que estamos más acustumbrados a tratar con las tablas, puede que por ser una construcción más intuitiva que las elaboraciones que se pueden realizar con el XML.

Supongamos que en una estantería existen diferentes frutas, tales como: naranjas, melones, sandías, limones, peras, ciruelas. La representación mediante una tabla es sumamente intuitiva:

Tabla 1. Frutas de la estantería

Naranjas Melones Sandías Limones Peras Ciruelas

Más sutil sería la representación en XML:

Tabla 2. Enumeración de las frutas que están en una estantería

<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Tue Jun 05 18:18:29 BST 2012 -->

<frutas_de_la_estantería>
	<fruta>Naranjas</fruta>
	<fruta>Melones</fruta>
	<fruta>Sandías</fruta>
	<fruta>Limones</fruta>
	<fruta>Peras</fruta>
	<fruta>Ciruelas</fruta>
</frutas_de_la_estantería>

Mediante el uso de los atributos de las etiquetas podriamos elaborar la misma información en sólo una línea:

Table 3. Enumeración de las frutas de una estantería utilizando una sólo línea de codificación

<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Tue Jun 05 18:18:29 BST 2012 -->

<frutas_de_la_estantería fruta1="Naranjas" fruta2="Melones" fruta3="Sandías" fruta4="Limones" fruta5="Peras" fruta6="Ciruelas"/>

Si en nuestro ejemplo hubiesemos considerado más de una estantería estariamos tratando un sistema de información de manera similar al otro, ya que tendríamos dos filas en la tabla y dos líneas de información en el código XML.

En esta entrada he hecho una introducción. El concepto de etiqueta es más amplio ya que su utilización va a dar lugar a que en el documento se formen distintas estructuras que nos van a permitir una alta abstracción en la manera de presentar la información, como la que ya hemos visto en el ejemplo, o añadir cierta información para que los procesadores entiendan lo que se traen entre manos, lo cual, por supuesto, no es ni más ni menos que los nosotros deseamos.

lunes, 16 de abril de 2012

Las listas simples en XSLT


Cuando hablamos de listas simples nos referimos a aquellas listas que sólo tienen un nivel. Para elaborar una lista simple con XSLT podemos usar  el elemento xsl:number. Sin embargo, vamos a ver que en XSLT existe una manera alternativa de realizar una lista numerada. En ambos casos el resultado que conseguimos es el mismo que si usásemos las etiquetas <lo><li> de HTML,
Empezamos por el método que se utiliza para realizar una lista numerada en HTML. El siguiente código HTML la ejecuta:
<lo>
    <li>flores
    </li>
    <li>cuadros
    </li>
    <li>copas
    </li>
    <li>vasos
    </li>
    </lo>
Producirá la siguiente salida en pantalla:
  1. flores
  2. cuadros
  3. copas
  4. vasos

Ejecución de una lista numerada simple XSLT mediante la utilización de la función position() de XPath


La función de XPath position() nos da el índice que un nodo ocupa en el orden de proceso teniendo en cuenta todos los demás nodos que se procesan al mismo tiempo que él. Un poco embrollado me quedó. Por ejemplo, si se han de procesar 20 nodos el primero de la lista tendrá position()=1, el segundo position()=2, etc..
Supongamos el siguiente documento XML, que contiene las Islas Canarias:
<?xml version="1.0" encoding="UTF-8"?>
    <!-- New document created with EditiX at Mon Apr 16 22:48:44 BST 2012 -->
    <!-- Islas Canarias -->
    <islas>
    <isla>La Palma
    </isla>
    <isla>La Gomera
    </isla>
    <isla>El Hierro
    </isla>
    <isla>Tenerife
    </isla>
    <isla>Gran Canaria
    </isla>
    <isla>Lanzarote
    </isla>
    <isla>Fuerteventura
    </isla>
    </islas>
El código XSLT necesario para realizar la lista numerada por el método de la función XPath position() será el siguiente:
<?xml version="1.0" encoding="UTF-8"?>
    <!-- New document created with EditiX at Tue Apr 17 00:09:53 BST 2012 -->
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="islas">
    <xsl:apply-templates select="isla"/>
    </xsl:template>
    <xsl:template match="isla">
    <xsl:value-of select="position(  )"/>
    <xsl:text>. </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>
</xsl:text>
    </xsl:template>
    </xsl:stylesheet>
Fíjate que el método de la hoja de transformación es texto (method="text"). O sea, el fichero de salida tendrá el formato texto. Es importante ese extremo para evaluar la salida, que será la siguiente:

1. La Palma

2. La Gomera

3. El Hierro

4. Tenerife

5. Gran Canaria

6. Lanzarote

7. Fuerteventura

El resultado en mi programa de transformación EditiX me produce una salida inesperada, que consiste en que intercala dos saltos de línea entre los nombres de las islas en lugar de uno, tal como la hoja de transformación contiene en las líneas 12 y 13. Tendría que investigar el motivo. De momento lo dejo así.

Si quisiera una transformación HTML, la hoja tendría que ser redactada de una manera ligeramente diferente porque, recordemos, el salto de línea en HTML se consigue con <br>, en lugar de insertar (ascii 10) para lograr el mismo resultado
<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Wed Apr 18 22:59:06 BST 2012 -->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:output method="html"/>
 
 <xsl:template match="/">
 <html>
  <body>
  <xsl:apply-templates select="islas" />
  </body>
 </html>
 </xsl:template>
 
 <xsl:template match="islas">
  <xsl:apply-templates select="isla"/>
  </xsl:template>
  
   <xsl:template match="isla">
   <xsl:value-of select="position(  )"/>
   <xsl:text>. </xsl:text>
   <xsl:value-of select="."/>
   <br/>
   </xsl:template>
   
</xsl:stylesheet>
La transformación dará como salida html la siguiente:
<html>
   <body>1. La Palma
       
      <br>2. La Gomera
       
      <br>3. El Hierro
       
      <br>4. Tenerife
       
      <br>5. Gran Canaria
       
      <br>6. Lanzarote
       
      <br>7. Fuerteventura
       
      <br></body>
</html>
Código que, por supuesto se verá desde el navegador exactamente igual que la salida para texto que puse más arriba

1. La Palma

2. La Gomera

3. El Hierro

4. Tenerife

5. Gran Canaria

6. Lanzarote

7. Fuerteventura


Ejecución de una lista numerada simple XSLT mediante la utilización del elemento xsl:number

Simplemente sustituimos en el código de la hoja de transformación anterior la línea que contiene la expresión xsl:value-of select="position()" por la expresión del elemento <xsl:number />, de tal forma que la hoja de transformación nos queda así:

<?xml version="1.0" encoding="UTF-8"?>
<!-- New document created with EditiX at Wed Apr 18 22:59:06 BST 2012 -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="islas" />
</body>
</html>
</xsl:template>
<xsl:template match="islas">
<xsl:apply-templates select="isla"/>
</xsl:template>
<xsl:template match="isla">
<!-- Aquí es donde cambiamos el código para introducir el elemento mumber -->
<!-- en lugar de la función position -->
<xsl:number />
<xsl:text>. </xsl:text>
<xsl:value-of select="."/>
<br/>
</xsl:template>
</xsl:stylesheet>

Numeración de listas en XSLT


La instrucción xsl:number de XSLT permite la creación de listas numeradas. En español puedes consultar la manera de usar este elemento en msdn de Microsoft. La traducción que esta página ha dado a lo que el elemento hace no me parece adecuada, ya que han trasladado desde el inglés que “inserta un número con formato en el árbol de resultados”, lo cual, en mi opinión, no describe en profundidad sus posibilidades.
Este elemento permite hacer numeraciones simples de los nodos que elijas a partir del árbol del documento primario XML. También permite realizar numeraciones complejas bien sea mediante la utilización de varios niveles de profundidad o mediante la utilización de números romanos, letras en orden alfabético y mayúsculas y minúsculas.
Lo normal será que dado un documento XML elijas la totalidad o una parte de ese documento para mostrarlo. Claro, como aquí hablamos de XSLT, utilizarás una transformación para realizar lo que pretendes. Una manera de presentar adecuadamente tus nodos estriba en usar el método porque es muy eficiente y clarificador numerar y clasificar los nodos que quieras presentar. 
Si tienes un árbol XML que contiene los resultados de tu liga deportiva favorita, podrías desear enviar a un amigo o publicar en tu blog la clasificación. Necesariamente ese mensaje o esa entrada contendrá una lista donde quede claro cuales son los mejores equipos clasificados y cual sea su orden en función de sus méritos deportivos: los goles o los puntos, los tiempos, etc. Entonces, a partir, del árbol XML que contiene las puntuaciones de los equipos que participan en la liga elaborarás una salida XSLT que presente todos una parte de los equipos ordenados por el criterio que elijas y además lo señale específicamente.
No debes confundir el método xsl:sort con el método xsl:number, el primero ordenará los nodos que elijas y el segundo añade la lista numérica 1., 2., ... etc., o bien la lista alfabética a., b,. … etc. Así:
  1. Real Madrid
  2. Barcelona
  3. Valencia
Las listas que se pueden realizar con el elemento xsl:number son las siguientes:
También el elemento permite llevar a cabo:
  • Inserción de formatos individuales en números
  • Comenzar las listas en un determinado elemento

martes, 27 de marzo de 2012

Transformación de un documento XML en una tabla


En esta entrada propongo un clásico de las transformaciones XSLT. Un clásico porque tabular datos en una tabla supone la manera más natural de presentarlos. La presentación de datos mediante una tabla es una manera muy intuitiva de comprenderlos. 
El fichero XML corresponde a una exportación a formato XML de la base de datos de aprendizaje "The Bank Schema", del libro Learning SQL, by Alan Beaulieu.
La tabla es la siguiente:
<prueba>
  <!-- Tabla officer -->
    <officer>
        <officer_id>1</officer_id>
        <cust_id>10</cust_id>
        <fname>John</fname>
        <lname>Chilton</lname>
        <title>President</title>
        <start_date>1995-05-01</start_date>
    </officer>
    <officer>
        <officer_id>2</officer_id>
        <cust_id>11</cust_id>
        <fname>Paul</fname>
        <lname>Hardy</lname>
        <title>President</title>
        <start_date>2001-01-01</start_date>
    </officer>
    <officer>
        <officer_id>3</officer_id>
        <cust_id>12</cust_id>
        <fname>Carl</fname>
        <lname>Lutz</lname>
        <title>President</title>
        <start_date>2002-06-30</start_date>
    </officer>
    <officer>
        <officer_id>4</officer_id>
        <cust_id>13</cust_id>
        <fname>Stanley</fname>
        <lname>Cheswick</lname>
        <title>President</title>
        <start_date>1999-05-01</start_date>
    </officer>
</prueba>
La hoja de transformación XSLT será:
<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Sun Mar 25 23:18:28 BST 2012 -->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- Elijo formato html como salida -->
 <xsl:output method="html"/>
<!-- Apunta el comienzo del árbol -->
<xsl:template match="/">
<html>
<body>
 <table  border="1">
 <!-- pongo los cabeceros a las columnas-->
     
  <tr>
                  <td><b>officer_id</b></td>
                  <td><b>cust_id</b></td>
                  <td><b>fname</b></td>
                  <td><b>lname</b></td>
                  <td><b>title</b></td>
                  <td><b>start_dat</b></td>
               </tr>
<!-- El corazón de la transformación. Recorre el nodo officer extrayendo el contenido y, a la vez, rellenando la tabla -->
<xsl:for-each select="*/officer"> <tr> <td><xsl:value-of select="officer_id"/></td> <td><xsl:value-of select="cust_id"/></td> <td><xsl:value-of select="fname"/> </td> <td><xsl:value-of select="lname"/></td> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="start_date"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
Esta será la salida de la transformación. Si no estás nada puesto en el tema de las transformaciones esto te sonará raro. Es cuestión de paciencia porque de la misma manera que a los mortales no nos es dado conocer todos los vericuetos de las metamorfosis que los dioses realizaban en la antigua Grecia, así se nos muestran esquivos los artilugios y los mecanismos necesarios para llevar a cabo nuestra empresa de lograr que los códigos transformen nuestras querencias.
Es difícil conseguir un programa que realice de forma correcta las transformaciones XSLT. Generalmente suelen ser editores de texto XML que llevan incorporado el transformador. Lo veremos con calma en otra entrada. Los buenos son de pago y los que están programados en código abierto son muy difíciles de tratar porque al estar enfocados a un lenguaje de programación tienes que tener dominio de Perl, C++, Java, etc, para entender qué es lo que se traen entre manos. 
Para esta entrada es suficiente con saber que utilizo EditiX, que tiene una versión restringida para uso académico que, a pesar de sus restricciones funciona muy bien para aprender. Las limitaciones afectan más bien a la productividad de la aplicación, o sea, el rendimiento y los atajos si se trata de utilizarla para labores profesionales. La misma aplicación te avisa si tratas de usar tareas que están limitadas.
Si te fijas verás que la hoja de transformación contiene al principio del texto el programa que la realiza. Es un mera publicidad, imagino que se trata de un recurso de sus diseñadores para seguir la pista de quienes los utilizamos. Lo dejo porque de alguna manera hay que agradecer que permitan utilizar gratuitamente un recurso tan potente y versátil.

<html>
   <body>
      <table border="1">
         <tr>
            <td><b>officer_id</b></td>
            <td><b>cust_id</b></td>
            <td><b>fname</b></td>
            <td><b>lname</b></td>
            <td><b>title</b></td>
            <td><b>start_dat</b></td>
         </tr>
         <tr>
            <td>1</td>
            <td>10</td>
            <td>John</td>
            <td>Chilton</td>
            <td>President</td>
            <td>1995-05-01</td>
         </tr>
         <tr>
            <td>2</td>
            <td>11</td>
            <td>Paul</td>
            <td>Hardy</td>
            <td>President</td>
            <td>2001-01-01</td>
         </tr>
         <tr>
            <td>3</td>
            <td>12</td>
            <td>Carl</td>
            <td>Lutz</td>
            <td>President</td>
            <td>2002-06-30</td>
         </tr>
         <tr>
            <td>4</td>
            <td>13</td>
            <td>Stanley</td>
            <td>Cheswick</td>
            <td>President</td>
            <td>1999-05-01</td>
         </tr>
      </table>
   </body>
</html>


Para acabar muestro la tabla tal como saldría en el navegador, o sea la interpretación del código anterior

officer_id cust_id fname lname title start_dat
1 10 John Chilton President 1995-05-01
2 11 Paul Hardy President 2001-01-01
3 12 Carl Lutz President 2002-06-30
4 13 Stanley Cheswick President 1999-05-01
Si quisieramos embellecerla: CSS al canto. Pinceladitas de color en las estructuras, digo

domingo, 25 de marzo de 2012

Convertir un documento XML a formato CVS

Mysql no da facilidades para la importación de documento en formato XML. Todo pasa por interminables sesiones de PHP de lo más raras. No termino de quedarme con el asunto de las librerías y todas esas cuestiones. Tampoco he logrado importar ningún documento XML a una base de datos. No hay manera. Siempre da error, si no es por una cuestión es por otra. Buscar en internet sobre este asunto es oír cientos de llamadas desesperadas de actuantes que quieren pasar un documento XML a una tabla MYSQL. Interminables listas de foros donde está la pregunta pero no aparece la respuesta. Eso y la publicidad que todo lo llena. Una pérdida de tiempo.
En algún sitio he visto que una transformación puede solucionar el asunto, por ejemplo aquí: transformación xml a cvs-
Añado la mía con unas explicaciones.
El fichero XML corresponde a una exportación a formato XML de la base de datos "The Bank Schema" del libro Learning SQL, by Alan Beaulieu. La tabla es la siguiente:
El fichero XML es:

<prueba>
  <!-- Tabla officer -->
    <officer>
        <officer_id>1</officer_id>
        <cust_id>10</cust_id>
        <fname>John</fname>
        <lname>Chilton</lname>
        <title>President</title>
        <start_date>1995-05-01</start_date>
    </officer>
    <officer>
        <officer_id>2</officer_id>
        <cust_id>11</cust_id>
        <fname>Paul</fname>
        <lname>Hardy</lname>
        <title>President</title>
        <start_date>2001-01-01</start_date>
    </officer>
    <officer>
        <officer_id>3</officer_id>
        <cust_id>12</cust_id>
        <fname>Carl</fname>
        <lname>Lutz</lname>
        <title>President</title>
        <start_date>2002-06-30</start_date>
    </officer>
    <officer>
        <officer_id>4</officer_id>
        <cust_id>13</cust_id>
        <fname>Stanley</fname>
        <lname>Cheswick</lname>
        <title>President</title>
        <start_date>1999-05-01</start_date>
    </officer>
</prueba>

La transformación del fichero que contiene la tabla XML a otro fichero que contiene el texto CVS se consigue mediante una hoja de transformación XSLT que aquí transcribo.

<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Sun Mar 25 22:06:58 BST 2012 -->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- Elijo formato texto como salida -->
 <xsl:output method="text"/>
<!-- Apunta el comienzo del árbol -->
<xsl:template match="prueba">
<!-- Seleccionará todas las filas  de la tabla, o lo que es lo mismo todos los nodos officer del árbol -->
  <xsl:apply-templates select="officer"/>
</xsl:template>
<!-- Apuntará a la primera fila  de la tabla, o sea al primer nodo-->
<xsl:template match="officer">
<!-- bucle para recorrer todos hijos del nodo officer-->
  <xsl:for-each select="*">
  <!-- Instrucción para seleccionar sucesivamente el valor de cada uno de los nodos -->
   <xsl:value-of select="."/>
   <!-- Instrucción para no añadir una coma al leer el último nodo hijo de officer. -->
   <xsl:if test="position() != last()">
   <!-- Instrucción para añadir una coma a continuación de cada nodo hijo de officer -->
    <xsl:value-of select="','"/>
   </xsl:if>
  </xsl:for-each>
   <!-- Cuando termina de leer la fila añade un salto de página y continua con la siguiente hasta finalizar -->
  <xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

El resultado es el siguiente:

1,10,John,Chilton,President,1995-05-01
2,11,Paul,Hardy,President,2001-01-01
3,12,Carl,Lutz,President,2002-06-30
4,13,Stanley,Cheswick,President,1999-05-01

sábado, 24 de marzo de 2012

Cuando Saturno fue enviado al tenebroso Tártaro

Cuando Saturno fue enviado al tenebroso Tártaro y el mundo quedó bajo el poder de Júpiter, nacieron los hijos de la edad de la plata, inferior a la del oro, pero más valiosa que la del rojo bronce. Júpiter redujo la duración de la antigua primavera, y con inviernos, veranos, irregulares otoños y breves primaveras dividió el año en cuatro estaciones. Por primera vez, entonces, el aire se volvió incandescente, abrasado por secas bocanadas de calor, y témpanos de hielo colgaron condensados por el viento. Por primera vez los hombres se refugiaron en casas: fueron sus casas cuevas, arbustos espesos y ramas enlazadas con cortezas; por primera vez se sembraron en largos surcos los frutos de Ceres, y los novillos mugieron oprimidos por el yugo.

xsl:apply-templates


<xsl:apply-templates
select = "node-set-expression"
mode = "QualifiedName">
<! -- (xsl:sort | xsl:with-param)*-- >
</xsl:apply-templates>
The xsl:apply-templates instruction tells the processor to search for and apply the highest-priority template in the stylesheet that matches each node identified by the select attribute.

Attributes

select, optional
This is an XPath expression that returns a node-set. Each node in this set will be processed further. If the select attribute is omitted, then all child nodes of the context node should be processed.
mode, optional
If the mode attribute is present, then only templates that have a matching mode attribute will be applied. If the mode attribute is absent, then only templates without a mode attribute will be applied.

Contents

The xsl:apply-templates element may have xsl:sort child elements to specify the order in which the selected nodes will be processed. Without any xsl:sort children, the default is to process nodes in document order.
The xsl:apply-templates element may have xsl:with-param child elements to pass parameter values to the matched templates.

xsl:decimal-format


<xsl:decimal-format    
name               = "QualifiedName">    
decimal-separator  = "char"    
grouping-separator = "char"    
infinity           = "string"    
minus-sign         = "char"    
NaN                = "string"    
percent            = "char"    
per-mille          = "char" 
zero-digit         = "char" 
digit              = "char"  
pattern-separator  = "char" /> 

The xsl:decimal-format top-level element defines a pattern by which the format-number( ) function can convert floating point numbers into text strings. The defaults work well for English, but details may change for other languages and locales, such as French or Chinese.

Attributes

name, optional
The string by which the format-number( ) function identifies the xsl:decimal-format element to use. If this attribute is omitted, then this element establishes the default decimal format used by the format-number( ) function.
decimal-separator, optional
The character that separates the integer part from the fractional point in a floating point number. This character is a period (decimal point) in English and a comma in French. It may be something else in other languages.
grouping-separator, optional
The character that separates groups of digits (e.g., the comma that separates every three digits in English).
infinity, optional
The string that represents IEEE 754 infinity; Infinity by default.
minus-sign, optional
The character prefixed to negative numbers; a hyphen by default.
NaN, optional
The string that represents IEEE 754 Not a Number; NaN by default.
percent, optional
The character that represents a percent; % by default.
per-mille, optional
The character that represents a per mille; by default.
zero-digit, optional
The character that represents zero; 0 by default. Digits 1 through 9 will be represented by the nine subsequent Unicode values after this one. For instance, setting zero-digit to A would set 1 to B, 2 to C, 3 to D, and so on. This is also the character used to represent 0 in format patterns.
digit, optional
The character that represents a digit in a format pattern; # by default.
pattern-separator, optional
The character that separates positive and negative subpatterns in a format pattern; ; by default.