<?xml version="1.0" encoding="ISO-8859-15"?>

<como titulo="XSLT Mini COMO" version="1.0" fecha="25-03-2002" xml:lang="es">

<autor nombre="Ibon Urretavizcaya" email="urreta@escomposlinux.org" datos="Autor"/>

<capitulo titulo="Licencia">

<listado titulo="'XSLT Mini COMO' bajo licencia FDL v1.1 o superior">
<elemento titulo="FDL" datos="Copyright (c) 2002 Ibon Urretavizcaya. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts and with no Back-Cover Texts. A copy of the license is included in the previous link." href="fdl.txt"/>
</listado>

</capitulo>

<capitulo titulo="Objetivos">

<parrafo>La información que hay en internet sobre XML y las aplicaciones que surgen sobre ella se están multiplicando rápidamente, pero para estar al día hay que doblegarse ante el inglés. Así que trataré de que este documento explique de forma clara y sencilla que es lo que a día de hoy XSLT ofrece.</parrafo>

<parrafo>Este mini como parte con un enfoque muy general del XML y profundiza rápidamente hacia los detalles del XSLT. Por ello recomiendo hacer una primera lectura rápida del mismo para comprender la estructura general, para más adelante estudiar las zonas de mayor interés para el lector. También pretendo que sirva como una guia de consulta rápida y para ese fin el índice enlaza con todas las tablas del documento.</parrafo>

</capitulo>


<capitulo titulo="Orientémonos en este mar de acrónimos">

<parrafo>Lo primero que crea confusión al aprender XML es la cantidad de acrónimos que existen, vamos a tratar de sentar unas bases firmes en las que poder apoyar tanta sucesión de siglas.</parrafo>

<parrafo>Bien XML es, dejándonos de tecnicismos, un estándar que ha gustado mucho a la comunidad de desarrolladores y ha generado en tiempo récord innumerables herramientas basadas en este estándar. XML no es más que una forma ordenada de escribir un archivo de texto y tomando esto como base podemos utilizar las nuevas herramientas que se han desarrollado para poder maximizar la productividad del contenido que hemos ordenado.</parrafo>

<parrafo>Y una vez definida la base empecemos a enumerar que acrónimos existen a su alrededor, voy a agruparlos en 5 grupos: evolución, extensiones, herramientas, esquemas y formatos.</parrafo>

<parrafo>La "evolución" agrupa aquellos acrónimos que son los pasos previos del XML y algunos cambios posteriores a su primera definición.</parrafo>

<listado titulo="Evolución">
<elemento titulo="SGML" datos="Estandard ISO."/>
<elemento titulo="XML" datos="Recomendación de W3C."/>
<elemento titulo="MinXML" datos="(Minimal XML) simplificación de la comunidad web."/>
<elemento titulo="Canonical XML" datos="Recomendación de W3C. Simplificación de XML."/>
</listado>

<parrafo>Las "extensiones" son ampliaciones comúnmente utilizadas de las características propias del XML.</parrafo>

<listado titulo="Extensiones">
<elemento titulo="Namespaces" datos="Permite mezclar lenguajes XML."/>
<elemento titulo="XInclude" datos="Permite combinar diferentes lenguajes XML."/>
<elemento titulo="XML Base" datos="Resuelve URIs relativas."/>
</listado>

<parrafo>Las "herramientas" agruparían aquellas aplicaciones cuyo objetivo es facilitar y potenciar el trabajo con archivos XML. Cada una se especializa en un campo y algunas se apoyan en otras para poder crear cada vez herramientas más especializadas.</parrafo>

<listado titulo="Herramientas">
<elemento titulo="XPath" datos="Para navegar por la estructura XML."/>
<elemento titulo="XPointer" datos="(XML Pointer Language) Para definir puntos exactos o rangos de la estructura XML."/>
<elemento titulo="XLink" datos="(XML Linking Language) utiliza XPointer y XPath. Para enlazar contenidos."/>
<elemento titulo="XQuery" datos="utiliza XPath y los tipos de datos definidos en XML Schema. Para extraer información como si de una base de datos se tratara."/>
<elemento titulo="XSLT" datos="(XSL Transformations) utiliza XPath. Para transformaciones de archivos XML en otros archivos de texto."/>
<elemento titulo="XSL-FO" datos="(XSL Formatting Objects) Para un control exacto y detallado de la apariencia."/>
<elemento titulo="XML Information Set" datos="Definición de terminología común XML."/>
<elemento titulo="XML Signature" datos="Firma Digital de recursos web."/>
<elemento titulo="XML Encryption" datos="Encriptación de recursos web."/>
<elemento titulo="XML Fragment Interchange" datos="Para trabajar con fragmentos XML."/>
<elemento titulo="XML Protocol" datos="Define protocolos de intercambio de información"/>
<elemento titulo="SOAP" datos="(Simple Object Access Protocol)."/>
<elemento titulo="XForms" datos="Formularios para inserción de datos."/>
<elemento titulo="RDF" datos="(Resource Description Framework) Definición de meta-información."/>
<elemento titulo="DOM" datos="(Document Object Model) para procesar código XML basado en la estructura."/>
<elemento titulo="SAX" datos="(Standard API for XML) para procesar código XML basado en eventos."/>
</listado>

<parrafo>Los "esquemas" son un caso especial de "herramientas", todas ellas tienen como objetivo definir que estructura debe de cumplir un archivo XML para ser válido. Existe una gran diversidad de esquemas y por ello he definido un grupo a parte. La variedad de esquemas se debe a que ninguno es "el mejor" y posiblemente no pueda existir un esquema perfecto para todas las necesidades, así que por ahora cada cual tiene su favorito en función de las necesidades.</parrafo>

<listado titulo="Esquemas">
<elemento titulo="DTD" datos="(Document Type Definition) de W3C."/>
<elemento titulo="XML-DATA" datos="de W3C."/>
<elemento titulo="DCD" datos="(Document Content Description) de W3C."/>
<elemento titulo="DDML" datos="(Document Definition Markup Language) de W3C."/>
<elemento titulo="SOX" datos="(Schema for Object-oriented XML) de W3C."/>
<elemento titulo="XML Schema" datos="de W3C."/>
<elemento titulo="Assertion Grammars" datos="de Dave Raggett."/>
<elemento titulo="Schematron" datos="de Rick Jellife."/>
<elemento titulo="Examplotron" datos="de Eric van der Vlist."/>
<elemento titulo="TREX" datos="(Tree Regular Expressions for XML) de James Clark."/>
<elemento titulo="RELAX" datos="de Makoto Murara."/>
<elemento titulo="RELAX NG" datos="de Makoto Murata y James Clark (unión de los dos anteriores)."/>
<elemento titulo="DSD" datos="(Document Structure Description) de BRICS y AT&amp;T."/>
</listado>

<parrafo>Si yo (con la carga subjetiva que ello conlleva) tuviese que destacar 3 esquemas elegiría: DTD, XML Schema y Relax NG.</parrafo>

<parrafo>DTD tiene su lugar garantizado porque ha sido utilizado durante mucho tiempo junto con el SGML, esta más orientado a contenido texto y por ello su soporte de tipos de datos es muy limitado, otra pega es que tiene su propia sintaxis que hay que aprender.</parrafo>

<parrafo>XML Schema resuelve los anteriormente citados inconvenientes del DTD, pero debido a su excesiva complejidad no ha terminado de convencer.</parrafo>

<parrafo>Relax NG es la evolución de los XML DTDs: sigue una definición de tipo gramática, es una aplicación XML, no necesita ser definido en el archivo XML origen, permite trabajar con tipos de datos, incluso importar tipos de forma sencilla, etc.</parrafo>

<parrafo>Los "formatos" agruparían aquellas aplicaciones XML cuyo objetivo es guardar un tipo de contenido, es al fin y al cabo un formato de archivo que aprovecha las ventajas del XML. Cada vez más programas utilizan el formato XML para guardar datos de configuración de la aplicación o incluso su formato original es XML.</parrafo>

<listado titulo="Formatos">
<elemento titulo="XHTML" datos="XMLización de HTML 4.0 de W3C."/>
<elemento titulo="CML" datos="(Chemical Markup Language)."/>
<elemento titulo="WML" datos="(Wireless Markup Language) para servicios WAP."/>
<elemento titulo="ThML" datos="(Theological Markup Language)."/>
<elemento titulo="SVG" datos="(Scalable Vector Graphics)."/>
<elemento titulo="DIA" datos="Formato original del programa."/>
<elemento titulo="Gnumeric" datos="Formato original del programa."/>
</listado>

</capitulo>


<capitulo titulo="Lo más básico del XML">
<parrafo>Lo primero que debemos hacer es declarar que nos encontramos ante un archivo XML, para ello los cinco primeros caracteres del archivo deben ser: " &lt;?xml ". Veamos que atributos puede tener, los opcionales están marcados en verde:</parrafo>

<listado titulo="Declaración &lt;?xml ... ?>">
<elemento titulo="version" datos="Versión XML necesaria para procesar el contenido.">
	<subelemento titulo="1.0"/>
</elemento>
<elemento titulo="encoding" datos="Define la codificación de texto utilizada." color="green">
        <subelemento titulo="UTF-8"/>
	<subelemento titulo="ISO-8859-1"/>
	<subelemento titulo="ISO-8859-15"/>
</elemento>
<elemento titulo="standalone" datos="Especifica si el archivo XML es autónomo o depende de un archivo DTD." color="green">
        <subelemento titulo="no"/>
	<subelemento titulo="yes"/>
</elemento>
</listado>

<parrafo>Voy a citar rápidamente las características básicas que un archivo XML debe cumplir para estar "bien formado". Si un archivo no esta "bien formado" al ser procesado dará un error y se detendrá el proceso.</parrafo>

<listado titulo="Reglas básicas del XML">
<elemento titulo="1 elemento root" datos="Todo el documento XML debe estar contenido en un único elemento, al que llamaremos 'root'."/>
<elemento titulo="Elementos anidados" datos="Todos los elementos deben contener elementos completos, es decir, deben contener tanto la etiqueta de apertura como la de cierre. Por tanto se debe respetar el orden inverso al de apertura a la hora de cerrarlos.">
	<subelemento titulo="&lt;elemento1>..&lt;elemento2>..&lt;/elemento2>..&lt;/elemento1>"/>
</elemento>
<elemento titulo="Atributos entre comillas" datos="Todos los atributos de los elementos deben tener su valor entre comillas. Pudiéndose elegir entre comillas simples o dobles.">
	<subelemento titulo="&lt;elemento atributo=&quot;valor&quot;> = &lt;elemento atributo='valor'>"/>
</elemento>
<elemento titulo="Mayúsculas y minúsculas" datos="Las etiquetas en XML, a diferencia con el HTML, diferencian entre mayúsculas y minúsculas. Salvo que tengas una buena excusa utiliza solo minúsculas y cúrate en salud."/>
<elemento titulo="Cerrar elementos" datos="Todos los elementos deben cerrarse con la etiqueta correspondiente.">
        <subelemento titulo="&lt;elemento>...&lt;/elemento>"/>
</elemento>
<elemento titulo="Elementos vacíos" datos="Los elementos que no contengan nada pueden abrir y cerrarse con una única etiqueta.">
	<subelemento titulo="&lt;elemento/&gt;"/>
</elemento>
</listado>

<parrafo>Otra posible causa de errores de "mal formación" de archivos XML se debe a la utilización de símbolos reservados XML para fines diferentes a los que XML define. Para evitarlo deben ser sustituidos:</parrafo>
<listado titulo="Símbolos reservados">
<elemento titulo="&lt;" datos="&amp;lt;"/>
<elemento titulo="&amp;" datos="&amp;amp;"/>
<elemento titulo="&gt;" datos="&amp;gt;"/>
<elemento titulo="&quot;" datos="&amp;quot;"/>
<elemento titulo="&apos;" datos="&amp;apos;"/>
</listado>

<parrafo>Por último, citar que existen 2 atributos definidos por XML, los cuales pueden utilizarse en cualquier elemento:</parrafo>

<listado titulo="Atributos XML">
<elemento titulo="xmlns:*" datos="Permite definir 'namespaces'. Es decir, definen prefijos que permiten diferenciar entre elementos con el mismo nombre."/>
<elemento titulo="xml:lang" datos="Permite definir el idioma en el que esta el contenido. El idioma debe definirse con 2 letras según la ISO-639 y puede añadirsele un subcódigo de 2 letras del país según la ISO-3166. Por ejemplo: 'es-ES'.">
	<subelemento titulo="ISO-639" href="http://lcweb.loc.gov/standards/iso639-2/langhome.html"/>
	<subelemento titulo="ISO-3166" href="http://www.ics.uci.edu/pub/ietf/http/related/iso3166.txt"/>
</elemento>
</listado>

</capitulo>


<capitulo titulo="Sintaxis XPath">

<listado titulo="XML Path Language (XPath)">
<elemento titulo="Versión 1.0" datos="Recomendación W3C 16 Noviembre 1999" href="http://www.w3.org/TR/xpath">
	<subelemento titulo="versión explicada en este mini-como"/>
</elemento>
<elemento titulo="Versión 2.0" datos="Boceto de trabajo W3C 20 Diciembre 2001" href="http://www.w3.org/TR/xpath20"/>
</listado>

<parrafo>No es objeto de este mini como definir la sintaxis de XPath, pero como su utilización es ineludible voy a resumir sus puntos básicos, después con los ejemplos XSLT explicaré con mayor detalle cada punto. Téngase en cuenta que solo con un gran dominio sobre XPath es posible maximizar el rendimiento de XSLT.</parrafo>

<parrafo>XPath es un lenguaje no-XML que permite identificar partes de documentos XML. Para XPath un documento XML no es más que un árbol de nodos, existen 7 tipos de nodos:</parrafo>

<listado titulo="Nodos">
<elemento titulo="Nodo 'root'" datos="Contiene al elemento 'root', es decir todo el documento.">
	<subelemento titulo="/"/>
</elemento>
<elemento titulo="Nodos elemento" datos="Contienen un elemento">
        <subelemento titulo="*"/>
</elemento>
<elemento titulo="Nodos atributo" datos="Contienen el atributo de un elemento.">
        <subelemento titulo="@*"/>
</elemento>
<elemento titulo="Nodos texto" datos="Contienen el texto entre las etiquetas de un elemento.">
        <subelemento titulo="text()"/>
</elemento>
<elemento titulo="Nodos comentario" datos="Contienen un comentario del autor.">
        <subelemento titulo="comment()"/>
</elemento>
<elemento titulo="Nodos instrucción" datos="Contienen instrucciones en otro lenguaje de programación.">
        <subelemento titulo="processing-instruction()"/>
</elemento>
<elemento titulo="Nodos 'namespace'" datos="Contiene la definición de un 'namespace'.">
	<subelemento titulo="namespace()"/>
</elemento>
</listado>

<parrafo>Existen 3 tipos de operadores que podemos utilizar: matemáticos, boléanos y de expresiones.</parrafo>

<listado titulo="Operadores matemáticos">
<elemento titulo="+" datos="Suma."/>
<elemento titulo="-" datos="Resta."/>
<elemento titulo="*" datos="Multiplicación."/>
<elemento titulo="div" datos="División."/>
<elemento titulo="mod" datos="Resto de una división."/>
</listado>

<parrafo/>

<listado titulo="Operadores boléanos">
<elemento titulo="=" datos="Igual."/>
<elemento titulo="&lt;" datos="Menor."/>
<elemento titulo="&lt;=" datos="Menor o igual."/>
<elemento titulo=">" datos="Mayor."/>
<elemento titulo=">=" datos="Mayor o igual."/>
<elemento titulo="!=" datos="Diferente."/>
<elemento titulo="and" datos="Y."/>
<elemento titulo="or" datos="O."/>
</listado>

<parrafo/>

<listado titulo="Operadores de expresiones.">
<elemento titulo="/" datos="Para bajar al nodo hijo."/>
<elemento titulo="//" datos="Hace referencia a todos los nodos hijo del nodo actual."/>
<elemento titulo="." datos="Nodo actual.">
	<subelemento titulo="node()"/>
</elemento>
<elemento titulo=".." datos="Para subir al nodo padre."/>
<elemento titulo="@" datos="Hace referencia a los nodos atributo del elemento actual."/>
<elemento titulo="|" datos="Permite unir varias expresiones Xpath."/>
<elemento titulo="*" datos="Permite seleccionar cualquier nodo sea cual sea su nombre."/>
<elemento titulo="[]" datos="El predicado permite definir filtros que seleccionen los nodos que nos interesan."/>
<elemento titulo="$" datos="Precede a un nombre de variable."/>
</listado>

<parrafo>Hasta ahora hemos visto las expresiones más comunes para moverse por el árbol de nodos, las cuales son iguales a las utilizadas para moverte por el sistema de ficheros Unix. Pero existen más expresiones y para utilizarlas deberemos utilizar la sintaxis no abreviada, denominada también como ejes:</parrafo>

<listado titulo="Ejes">
<elemento titulo="child::*" datos="El eje hijo contiene todos los nodos comentario, elemento, instrucción y texto hijos del nodo actual.">
	<subelemento titulo="/"/>
</elemento>
<elemento titulo="parent::*" datos="El eje padre contiene el nodo padre del nodo actual.">
	<subelemento titulo=".."/>
</elemento>
<elemento titulo="self::*" datos="Este eje contiene el nodo actual.">
	<subelemento titulo="."/>
</elemento>
<elemento titulo="atributte::*" datos="El eje atributo contiene todos los nodos atributo del nodo actual.">
        <subelemento titulo="@"/>
</elemento>
<elemento titulo="ancestor::*" datos="El eje ancestro contiene el nodo padre, abuelo, bisabuelo, etc...  del nodo actual hasta llegar al nodo 'root'. Este eje contiene el nodo 'root', salvo que el nodo actual sea el nodo 'root'."/>
<elemento titulo="ancestor-or-self::*" datos="Este eje contiene el nodo actual y el nodo padre, abuelo, bisabuelo, etc...  del nodo actual hasta llegar al nodo 'root'. Siempre incluye el nodo 'root'."/>
<elemento titulo="descendant::*" datos="El eje descendientes contiene todos los nodos comentario, elemento, instrucción y texto hijos, nietos, bisnietos, etc... del nodo actual."/>
<elemento titulo="descendant-or-self::*" datos="Este eje contiene el nodo actual y todos los nodos comentario, elemento, instrucción y texto hijos, nietos, bisnietos, etc... del nodo actual.">
	<subelemento titulo="//"/>
</elemento>
<elemento titulo="preceding-sibling::*" datos="Este eje contiene todos los nodos anteriores que comparten el mismo padre que el nodo actual. Si el nodo actual es un atributo o un 'namespace', al considerar que son nodos sin padre, este eje no contiene nada."/>
<elemento titulo="following-sibling::*" datos="Este eje contiene todos los nodos posteriores que comparten el mismo padre que el nodo actual. Si el nodo actual es un atributo o un 'namespace', al considerar que son nodos sin padre, este eje no contiene nada."/>
<elemento titulo="preceding::*" datos="Este eje contiene todos los nodos anteriores al nodo actual, excepto los nodos ancestro, atributo y 'namespace'."/>
<elemento titulo="following::*" datos="Este eje contiene todos los nodos posteriores al nodo actual, excepto los nodos descendientes, atributo y 'namespace'."/>
<elemento titulo="namespace::*" datos="Este eje contiene los nodos 'namespace' del nodo actual. Si el nodo actual no es un elemento este eje no contiene nada."/>
</listado>

</capitulo>


<capitulo titulo="Funciones XPath">

<parrafo>XPath, además de lo que hemos visto hasta ahora, define 27 funciones que facilitan mucho el trabajo. Vamos a agrupar las funciones en 4 grupos:</parrafo>

<listado titulo="Funciones con nodos">
<elemento titulo="position()" datos="Devuelve el numero de posición del nodo actual.">
	<subelemento titulo="elemento[position()=1] = elemento[1]"/>
</elemento>
<elemento titulo="last()" datos="Devuelve el numero de posición del último nodo.">
        <subelemento titulo="elemento[position()=last()]  es el último"/>
</elemento>
<elemento titulo="count()" datos="Devuelve el numero total de nodos.">
	<subelemento titulo="count(//elemento)"/>
</elemento>
<elemento titulo="id()" datos="Devuelve un conjunto de nodos que tengan ese identificador. El atributo con el identificador debe estar definido en el DTD como de tipo ID.">
	<subelemento titulo="id('es')"/>
	<subelemento titulo="id('es eu en pt jp')"/>
</elemento>
<elemento titulo="name()" datos="Devuelve una cadena de caracteres con el nombre completo del elemento, incluyendo el prefijo 'namespace'.">
	<subelemento titulo="name(elemento) es 'xsl:elemento'"/>
</elemento>
<elemento titulo="local-name()" datos="Devuelve una cadena de caracteres con el nombre local del elemento, sin el prefijo 'namespace'.">
        <subelemento titulo="local-name(elemento) es 'elemento'"/>
</elemento>
<elemento titulo="namespace-uri()" datos="Devuelve una cadena de caracteres con la URI asociada al 'namespace' del elemento.">
        <subelemento titulo="namespace-uri(elemento) es 'http://www.w3.org/1999/XSL/Transform'"/>
</elemento>
<elemento titulo="lang()" datos="Devuelve verdadero o falso en función de que el código de idioma sea igual o no al atributo xml:lang más cercano del nodo actual.">
	<subelemento titulo="si lang('es') es verdad esta en español"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="Funciones con cadenas de caracteres">
<elemento titulo="string()" datos="Convierte cualquier objeto en una cadena de caracteres."/>
<elemento titulo="starts-with()" datos="Devuelve verdadero o falso en función de que la primera cadena empiece o no con la segunda.">
	<subelemento titulo="starts-with('abcd','a') es verdad"/>
	<subelemento titulo="starts-with('abcd','b') es falso"/>
</elemento>
<elemento titulo="contains()" datos="Devuelve verdadero o falso en función de que la primera cadena contenga o no la segunda.">
        <subelemento titulo="contains('abcd','a') es verdad"/>
        <subelemento titulo="contains('abcd','b') es verdad"/>
</elemento>
<elemento titulo="substring-before()" datos="Devuelve la subcadena anterior a la segunda cadena encontrada en la primera cadena.">
        <subelemento titulo="substring-before('es-ES','-') es 'es'"/>
</elemento>
<elemento titulo="substring-after()" datos="Devuelve la subcadena posterior a la segunda cadena encontrada en la primera cadena.">
        <subelemento titulo="substring-before('es-ES','-') es 'ES'"/>
</elemento>
<elemento titulo="substring()" datos="Devuelve una subcadena de la primera cadena utilizando el primer numero como inicio y el segundo (si existe) como longitud.">
        <subelemento titulo="substring('abcdef', 3, 2) es 'cd'"/>
	<subelemento titulo="substring('abcdef', 4) es 'def'"/>
</elemento>
<elemento titulo="string-length()" datos="Devuelve un numero con la longitud de la cadena.">
	<subelemento titulo="string-length('abcdef') es 6"/>
</elemento>
<elemento titulo="normalize-space()" datos="Elimina los espacios anteriores y posteriores de la cadena y sustituye las sucesiones de espacios por un solo espacio."/>
<elemento titulo="concat()" datos="Devuelve una cadena concatenada de los objetos entre paréntesis."/>
<elemento titulo="translate()" datos="Devuelve una cadena a la que tomando como origen la primera cadena se le ha sustituido la segunda cadena por la tercera.">
        <subelemento titulo="translate('a-b-c','-','_') es 'a_b_c'"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="Funciones boleanas">
<elemento titulo="true()" datos="Siempre devuelve verdadero."/>
<elemento titulo="false()" datos="Siempre devuelve falso."/>
<elemento titulo="not()" datos="Cambia el valor de verdadero a falso y de falso a verdadero."/>
<elemento titulo="boolean()" datos="Convierte cualquier objeto en verdadero o falso."/>
</listado>

<parrafo/>

<listado titulo="Funciones numéricas">
<elemento titulo="number()" datos="Convierte cualquier objeto en un número."/>
<elemento titulo="round()" datos="Redondea el valor entre paréntesis."/>
<elemento titulo="floor()" datos="Redondea hacia abajo el valor entre paréntesis."/>
<elemento titulo="ceiling()" datos="Redondea hacia arriba el valor entre paréntesis."/>
<elemento titulo="sum()" datos="Suma el contenido."/>
</listado>

</capitulo>


<capitulo titulo="Centrémonos en el XSLT">

<listado titulo="XSL Transformations (XSLT)">
<elemento titulo="Versión 1.0" datos="Recomendación W3C 16 Noviembre 1999" href="http://www.w3.org/TR/xslt">
	<subelemento titulo="versión explicada en este mini-como"/>
</elemento>
<elemento titulo="Versión 2.0" datos="Boceto de trabajo W3C 20 Diciembre 2001" href="http://www.w3.org/TR/xslt20"/>
</listado>

<parrafo>XSLT es una aplicación que define un lenguaje para modificar archivos XML. Este lenguaje precisa definir que transformaciones se quieren hacer y a que partes del documento. Para lo primero el propio XSLT define unos elementos, pero para lo segundo XSLT se basa en la sintaxis que define XPath. Por lo tanto XSLT es un lenguaje que va a definir que transformaciones vamos a realizar y cada vez que precisemos seleccionar un elemento a modificar utilizaremos XPath.</parrafo>

<parrafo>XSLT al ser una aplicación XML, se escribe en archivos XML y debe seguir todas las reglas que ello implica. Tendremos a nuestra disposición los elementos y funciones que define XSLT, la sintaxis y funciones propias de XPath e incluso podremos utilizar otras aplicaciones como XLink y XPointer.</parrafo>

<parrafo>Para conseguir realizar la modificación deberemos escribir una hoja de estilo explicando, con la sintaxis apropiada, que queremos que el procesador XSLT haga con el archivo XML. La hoja de estilo tiene la extensión 'xsl' y una vez definida funcionará con cualquier procesador XSLT escrito en cualquier lenguaje y ejecutado en cualquier entorno.</parrafo>

<listado titulo="Procesadores XSLT con licencia libre">
<elemento titulo="Napa" datos="Kevin Jones.">
	<subelemento titulo="???" href="http://homepage.ntlworld.com/kjjones/"/>
</elemento>
<elemento titulo="Sablotron" datos="Ginger Alliance.">
	<subelemento titulo="C++" href="http://www.gingerall.com/charlie/ga/xml/p_sab.xml"/>
	<subelemento titulo="Perl" href="http://www.gingerall.com/charlie/ga/xml/x_sabperl.xml"/>
	<subelemento titulo="PHP" href="http://www.gingerall.com/charlie/ga/xml/x_sabphp.xml"/>
	<subelemento titulo="Python" href="http://www.gingerall.com/charlie/ga/xml/x_sabpyth.xml"/>
</elemento>
<elemento titulo="XML::XSLT" datos="Geert Josten y Egon Willighagen.">
	<subelemento titulo="Perl" href="http://xmlxslt.sourceforge.net/"/>
</elemento>
<elemento titulo="MDC-XSL" datos="Minoru Development Corporation.">
        <subelemento titulo="C++" href="http://mdc-xsl.sourceforge.net/"/>
</elemento>
<elemento titulo="Xalan" datos="Apache XML Project. (LotusXSL de Alphaworks, IBM)">
        <subelemento titulo="C++" href="http://xml.apache.org/xalan-c/index.html"/>
	<subelemento titulo="Java" href="http://xml.apache.org/xalan-j/index.html"/>
	<subelemento titulo="Python[Pyana]" href="http://pyana.sourceforge.net/"/>
</elemento>
<elemento titulo="jd.xslt" datos="Johannes Döbler.">
        <subelemento titulo="Java" href="http://www.aztecrider.com/xslt"/>
</elemento>
<elemento titulo="SAXON" datos="Michael H. Kay.">
        <subelemento titulo="Java" href="http://saxon.sourceforge.net/"/>
</elemento>
<elemento titulo="XT" datos="James Clark.">
        <subelemento titulo="Java" href="http://www.jclark.com/xml/xt.html"/>
</elemento>
<elemento titulo="Koala XSL Engine" datos="INRIA.">
        <subelemento titulo="Java" href="http://kaluta.ilog.fr/XML/xslProcessor/"/>
</elemento>
<elemento titulo="XSL:P" datos="Keith Visco.">
        <subelemento titulo="Java [enlace-roto]" href="http://www.clc-marketing.com/xslp/"/>
</elemento>
<elemento titulo="4suite" datos="Fourthought.">
<subelemento titulo="python" href="http://4suite.org/"/>
</elemento>
<elemento titulo="Gnome libxslt library" datos="Daniel Veillard.">
<subelemento titulo="C" href="http://xmlsoft.org/XSLT/"/>
<subelemento titulo="perl[XML::LibXSLT]" href="http://theoryx5.uwinnipeg.ca/mod_perl/cpan-search?modinfo=12014"/>
</elemento>
<elemento titulo="XSLTC" datos="Olivier Gerardin.">
<subelemento titulo="C++" href="http://sourceforge.net/projects/xsltc"/>
</elemento>
<elemento titulo="Unicorn XSLT Processor" datos="Unicorn Enterprises.">
<subelemento titulo="C++" href="http://www.unicorn-enterprises.com/products_uxt.html"/>
</elemento>
</listado>

</capitulo>


<capitulo titulo="Puntos fuertes del XSLT">

<parrafo>La gran ventaja del XSLT es la capacidad de transformar una única fuente de información en infinidad de formatos y de adaptar el contenido y la presentación para que se adapte a cualquier medio, ya sea visual, inalámbrico, físico, temporal, braille, etc... el límite lo pone la imaginación, o la necesidad.</parrafo>

<parrafo>Otra de las ventajas es que por fin permite separar el contenido de la presentación, pudiéndose modificar aspectos visuales fácilmente sin que los contenidos se vean mezclados en el proceso.</parrafo>

<parrafo>Permite reutilizar los datos contenidos en formato XML para otros fines diferentes al original.</parrafo>

</capitulo>


<capitulo titulo="Funciones XSLT">

<parrafo>XSLT puede utilizar las funciones de XPath y además define 10 funciones propias. Vamos a utilizar el mismo sistema de agrupación que hemos utilizado antes:</parrafo>

<listado titulo="Funciones especiales">                                                                                               <elemento titulo="element-available()" datos="Comprueba si un elemento esta disponible. Tiene utilidad a la hora de utilizar elementos extendidos."/>
<elemento titulo="function-available()" datos="Comprueba si la función esta disponible. Tiene utilidad a la hora de utilizar funciones extendidas."/>
<elemento titulo="system-property()" datos="Devuelve información sobre el procesador XSLT.">
	<subelemento titulo="xsl:version"/>
	<subelemento titulo="xsl:vendor"/>
	<subelemento titulo="xsl:vendor-url"/>
</elemento>
<elemento titulo="unparsed-entity-uri()" datos="Devuelve la URI de la entidad no comprobada."/>
</listado>

<parrafo/>

<listado titulo="Funciones con nodos">
<elemento titulo="current()" datos="Devuelve el nodo actual. Fuera del predicado es igual a '.' de XPath, pero dentro del predicado puede no serlo."/>
<elemento titulo="document()" datos="Permite cargar el nodo 'root' de un documento XML."/>
<elemento titulo="generate-id()" datos="Genera una cadena de caracteres para cada nodo. Un mismo nodo siempre obtiene la misma cadena durante una misma transformación."/>
<elemento titulo="key()" datos="Lista el conjunto de nodos que pertenecen contienen cierta clave. Una función con mayores prestaciones que la función id() de XPath."/>
</listado>

<parrafo/>

<listado titulo="Funciones con cadenas de caracteres">
<elemento titulo="format-number()" datos="Convierte un numero a una cadena de caracteres siguiendo el patrón que se especifique. El patrón utiliza los valores definidos en el elemento 'xsl:decimal-format'."/>
</listado>

<parrafo>Para la función 'format-number()' vamos a definir la simbología que podemos utilizar para definir el patrón:</parrafo>

<listado titulo="Simbología del patrón de 'format-number()'">
<elemento titulo="0" datos="Un dígito, incluyendo los ceros a la izquierda y decimales. Definido en el atributo 'zero-digit' de 'xsl:decimal-format'."/>
<elemento titulo="#" datos="Un dígito, sin incluir los ceros a la izquierda y decimales. Definido en el atributo 'digit' de 'xsl:decimal-format'."/>
<elemento titulo="." datos="Separador decimal. Definido en el atributo 'decimal-separator' de 'xsl:decimal-format'."/>
<elemento titulo="," datos="Separador de grupos (mil). Definido en el atributo 'grouping-separator' de 'xsl:decimal-format'."/>
<elemento titulo=";" datos="Separador del patrón positivo y negativo. Definido en el atributo 'pattern-separator' de 'xsl:decimal-format'."/>
<elemento titulo="-" datos="Símbolo negativo. Definido en el atributo 'minus-sign' de 'xsl:decimal-format'."/>
<elemento titulo="%" datos="Divide entre 100 y muestra el símbolo de porcentaje. Definido en el atributo 'percent' de 'xsl:decimal-format'."/>
<elemento titulo="X" datos="Indica cualquier carácter para prefijo o sufijo. Definido en el atributo 'prefix' o 'suffix' de 'xsl:decimal-format'."/>
<elemento titulo="'" datos="Utilizado para proteger caracteres especiales en el prefijo o sufijo."/>
<elemento titulo="X*" datos="Indica cero o más ocurrencias de X."/>
<elemento titulo="(X | Y)" datos="Indica que X y Y son válidos."/>
<elemento titulo="X..Y" datos="Indica cualquier carácter entre X y Y."/>
<elemento titulo="S - T" datos="Indica que si caracteres en S, pero no en T. ???"/>
</listado>

<parrafo>A parte de estas funciones se pueden generar otras, llamadas funciones extendidas. Estas funciones pueden ahorrar mucho trabajo, pero debe saberse que se pierde compatibilidad de la hoja de estilo y posiblemente solo funcione en el procesador XSLT en el que fue desarrollada.</parrafo>

</capitulo>


<capitulo titulo="Elementos XSLT: atributos">

<parrafo>Antes de empezar con los elementos XSLT voy a hacer hincapié en los posibles contenidos de un atributo, que como ya sabemos tiene que estar entre comillas:</parrafo>

<listado titulo="Entre comillas">
<elemento titulo="&lt;xsl:* atributo= 'texto' /&gt;" datos="Expresión XPath que hace referencia al ELEMENTO 'texto'."/>
<elemento titulo='&lt;xsl:* atributo= "texto" /&gt;' datos="Igual al anterior."/>
<elemento titulo="&lt;xsl:* atributo= '&quot;texto&quot;' /&gt;" datos="El atributo toma como valor la PALABRA 'texto'."/>
<elemento titulo='&lt;xsl:* atributo= "&apos;texto&apos;" /&gt;' datos="Igual al anterior."/>
<elemento titulo="&lt;xsl:* atributo= '@texto' /&gt;" datos="Expresión XPath que hace referencia al ATRIBUTO 'texto'."/>
<elemento titulo='&lt;xsl:* atributo= "@texto" /&gt;' datos="Igual al anterior."/>                                                            <elemento titulo="&lt;xsl:* atributo= '&quot;@texto&quot;' /&gt;" datos="El atributo toma como valor la PALABRA '@texto'."/>
<elemento titulo='&lt;xsl:* atributo= "&apos;@texto&apos;" /&gt;' datos="Igual al anterior."/>
<elemento titulo="&lt;* atributo= '{@texto}' /&gt;" datos="ATENCIÓN: Permite aplicar al atributo de un elemento cualquiera (NO xsl:*) el valor de un atributo directamente. Es muy útil."/>
<elemento titulo='&lt;* atributo= "{@texto}" /&gt;' datos="Igual al anterior."/>
</listado>

</capitulo>


<capitulo titulo="Elementos XSLT: 'root'">

<parrafo>La estructura básica de una hoja de estilo es la siguiente:</parrafo>

<codigo tipo="xsl">
<nuevo color="white">&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	...
&lt;/xsl:stylesheet></nuevo>
</codigo>

<parrafo>El ejemplo <numcap/>.1 declara que nos encontramos ante un archivo XML y define un elemento root 'xsl:stylesheet' que contendrá toda la información sobre las transformaciones a realizar. El resto de la línea define el prefijo 'xsl' como el indicado para todos los elementos del lenguaje XSLT. En la siguiente tabla aparecen todos los atributos de este elemento, están señalados en verde los opcionales.</parrafo> 

<listado titulo="&lt;xsl:stylesheet> = &lt;xsl:transform>">
<elemento titulo="version" datos="Define que versión de XSLT necesita la hoja de estilo.">
        <subelemento titulo="1.0"/>
</elemento>
<elemento titulo="xmlns:xsl" datos="Define la URI para el 'namespace' XSL.">
        <subelemento titulo="http://www.w3.org/1999/XSL/Transform"/>
</elemento>
<elemento titulo="xmlns:*" datos="Define la URI para cualquier otro 'namespace'." color="green"/>
<elemento titulo="id" datos="Define un identificador para la hoja de estilo." color="green"/>
<elemento titulo="extension-element-prefixes" datos="Define los prefijos 'namespace' para llamar a elementos extendidos." color="green"/>
<elemento titulo="exclude-result-prefixes" datos="Define que prefijos 'namespace' no deben ser enviados al resultado." color="green"/>
</listado>

</capitulo>


<capitulo titulo="Elementos XSLT: 'top level'">

<parrafo>Los elementos 'top level' son los únicos que pueden ser hijos de 'xsl:stylesheet'. Para facilitar su aprendizaje voy a mostrar los 12 elementos agrupados en 4 grupos:</parrafo>

<listado titulo="Definen el modelo">
<elemento titulo="xsl:template" datos="Contiene un modelo que será aplicado a los nodos que haya que transformar."/>
<elemento titulo="xsl:attribute-set" datos="Define grupos de atributos que posteriormente serán aplicados a elementos.">
	<subelemento titulo="Solo puede tener hijos 'xsl:attribute'"/>
</elemento>
<elemento titulo="xsl:import" datos="Importa modelos de otras hojas de estilo dándoles una prioridad inferior a los modelos de la hoja actual.">
	<subelemento titulo="Debe definirse al principio"/>
	<subelemento titulo="Sin hijos"/>
</elemento>
<elemento titulo="xsl:include" datos="Permite incluir modelos de otras hojas de estilo con igual prioridad que los modelos de la hoja actual.">
	<subelemento titulo="Sin hijos"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="Definen el formato del resultado">
<elemento titulo="xsl:output" datos="Define las características básicas del formato del resultado.">
	<subelemento titulo="Sin hijos"/>
</elemento>
<elemento titulo="xsl:strip-space" datos="Definen los elementos a los que se les va a quitar los espacios sobrantes.">
	<subelemento titulo="Sin hijos"/>
</elemento>
<elemento titulo="xsl:preserve-space" datos="Definen los elementos a los que no se les va a quitar los espacios sobrantes.">
	<subelemento titulo="Sin hijos"/>
</elemento>
<elemento titulo="xsl:decimal-format" datos="Permite definir el formato en el que los valores numéricos serán mostrados. Permite definir varios estilos por medio de nombres, sin nombre es el estilo por defecto.">
	<subelemento titulo="Sin hijos"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="Definen un seudo-lenguaje de programación">
<elemento titulo="xsl:param" datos="Define el nombre y valor de un parámetro. Esta diseñado para guardar un valor, pasarlo entre modelos, e incluso entre el procesador XSLT y la hoja de estilo.">
	<subelemento titulo="Debe definirse al principio"/>
	<subelemento titulo="Si es hijo de 'xsl:stylesheet' es global"/>
	<subelemento titulo="En caso contrario es local"/>
</elemento>
<elemento titulo="xsl:variable" datos="Define una función que devuelve un valor en función del contenido de la variable.">
	<subelemento titulo="Si es hijo de 'xsl:stylesheet' es global"/>
	<subelemento titulo="En caso contrario es local"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="Definen características especiales">
<elemento titulo="xsl:namespace-alias" datos="Permite definir un alias para un 'namespace'.">
	<subelemento titulo="Sin hijos"/>
</elemento>
<elemento titulo="xsl:key" datos="Define una clave que facilita la posterior búsqueda de nodos mediante la función key().">
	<subelemento titulo="Sin hijos"/>
</elemento>
</listado>

</capitulo>


<capitulo titulo="Elementos XSLT: restantes">

<parrafo>Ahora vamos a agrupar de igual modo los 21 elementos restantes que define XSLT:</parrafo>

<listado titulo="Definen el modelo">
<elemento titulo="xsl:value-of" datos="Calcula el valor de una expresión XPath."/>
<elemento titulo="xsl:copy" datos="Permite copiar un elemento, pero no copia ni sus atributos ni sus hijos."/>
<elemento titulo="xsl:copy-of" datos="Permite copiar un elemento incluyendo sus atributos, sus hijos, nietos, etc.">
	<subelemento titulo="Sin hijos"/>
</elemento>
<elemento titulo="xsl:apply-templates" datos="Define los nodos a los que hay que aplicar los modelos apropiados. Puede definir también que parámetros se le deben pasar al modelo.">
	<subelemento titulo="Solo puede tener hijos 'xsl:with-param' y 'xsl:sort'"/>
</elemento>
<elemento titulo="xsl:call-template" datos="Permite llamar a un modelo en concreto por su nombre. Puede definir también que parámetros se le deben pasar al modelo.">
	<subelemento titulo="Solo puede tener hijos 'xsl:with-param'"/>
</elemento>
<elemento titulo="xsl:element" datos="Permite crear un elemento."/>
<elemento titulo="xsl:attribute" datos="Permite añadir un atributo a un elemento.">
	<subelemento titulo="Debe definirse al principio"/>
</elemento>
<elemento titulo="xsl:text" datos="Permite escribir texto de forma literal en el archivo resultante."/>
<elemento titulo="xsl:comment" datos="Permite crear comentarios en el archivo resultante. También permite generar definiciones CSS.">
	<subelemento titulo="&lt;!-- ... --&gt;"/>
</elemento>
<elemento titulo="xsl:processing-instruction" datos="Permite crear instrucciones en otros lenguajes de programación en el archivo resultante."/>
<elemento titulo="xsl:apply-imports" datos="Permite aplicar modelos importados aumentando su prioridad.">
	<subelemento titulo="Sin hijos"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="Definen el formato del resultado">
<elemento titulo="xsl:number" datos="Permite contar elementos y mostrar la numeración en el formato deseado. También puede utilizarse para dar formato a valores numéricos.">
	<subelemento titulo="Sin hijos"/>
</elemento>
<elemento titulo="xsl:sort" datos="Ordena un conjunto de nodos.">
	<subelemento titulo="Sin hijos"/>
	<subelemento titulo="Debe ser hijo de 'xsl:apply-templates' o 'xsl:for-each'"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="Definen un seudo-lenguaje de programación">
<elemento titulo="xsl:if" datos="Define una condición y solo si se cumple se procesará su contenido."/>
<elemento titulo="xsl:choose" datos="Permite elegir entre varias situaciones definidas con 'xsl:when', en el caso de que no se cumpla ninguna elige el elemento 'xsl:otherwise'.">
	<subelemento titulo="Solo puede tener hijos 'xsl:when' y 'xsl:otherwise'"/>
</elemento>
<elemento titulo="xsl:when" datos="Define una condición dentro del elemento 'xsl:choose' y si es la primera en cumplirse se procesa su contenido.">
	<subelemento titulo="Debe ser hijo de 'xsl:choose'"/>
</elemento>
<elemento titulo="xsl:otherwise" datos="Define que procesar dentro del elemento 'xsl:choose' en el caso de que las condiciones de los elementos 'xsl:when' precedentes no se cumplan.">
	<subelemento titulo="Debe ser hijo de 'xsl:choose'"/>
	<subelemento titulo="Debe definirse al final"/>
</elemento>
<elemento titulo="xsl:for-each" datos="Recorre, de uno en uno, el conjunto de nodos a los que hace referencia.">
	<subelemento titulo="Puede tener hijos 'xsl:sort' al principio"/>
</elemento>
<elemento titulo="xsl:with-param" datos="Selecciona un parámetro que será pasado al modelo.">
	<subelemento titulo="Debe ser hijo de 'xsl:apply-templates' o 'xsl:call-template'"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="Definen características especiales">
<elemento titulo="xsl:fallback" datos="Define un modelo que será utilizado en el caso de que un elemento extendido no se encuentre disponible."/>
<elemento titulo="xsl:message" datos="Permite mandar un mensaje a la salida de texto. Ayuda a localizar errores en las hojas de estilo."/>
</listado>

</capitulo>


<capitulo titulo="Transformaciones: básicas I">

<parrafo>Hasta ahora nos hemos limitado a citar de forma ordenada todas las herramientas que podemos utilizar, es hora de empezar a ver ejemplos. Cada vez que utilicemos un elemento nuevo explicaremos en una tabla todos sus posibles atributos, señalando los opcionales en verde. La hoja de estilo más sencilla que podemos definir contiene sólo el elemento 'xsl:stylesheet'.</parrafo>

<codigo tipo="xsl">
<nuevo color="white">&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
&lt;/xsl:stylesheet></nuevo>
</codigo>

<parrafo>Para poder utilizar esta hoja de estilo necesitamos un archivo XML a transformar. Supongamos que el ejemplo <numcap/>.2 contiene el listado de obras de una biblioteca:</parrafo>

<codigo tipo="xml">
&lt;?xml version="1.0"?>
&lt;biblioteca nombre="Biblioteca Municipal">
	&lt;libro>Matemáticas&lt;/libro>
	&lt;libro>Historia&lt;/libro>
	&lt;revista>Ciencia&lt;/revista>
	&lt;revista>OVNI&lt;/revista>
&lt;/biblioteca>
</codigo>

<parrafo>Si procesamos el documento XML <numcap/>.2 con la hoja de estilo <numcap/>.1 obtenemos el documento resultante <numcap/>.3:</parrafo>
             
<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?> 
Matemáticas
Historia
Ciencia 
OVNI
</codigo>                                                                                                                             

<parrafo>Con este ejemplo podemos ver que transformaciones por defecto realiza el procesador XSLT ante una hoja de estilo sin contenido: el documento resultante tiene una declaración XML con codificación UTF-8 y muestra el contenido de todas las etiquetas, pero no los nombres de la etiquetas ni sus atributos. Supongamos que el documento que queremos obtener sea un archivo mostrando como título el nombre de la biblioteca:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<nuevo color="white">	&lt;xsl:template match="biblioteca">
		&lt;xsl:value-of select="@nombre"/>
	&lt;/xsl:template></nuevo>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>En la hoja de estilo <numcap/>.4 hemos definido un elemento 'xsl:template' el cual contiene un modelo que se limita a un elemento vacío 'xsl:value-of'. El elemento 'xsl:template' se aplicará a los elementos que se llamen 'biblioteca', es este caso el elemento 'root'. El elemento 'xsl:value-of' con el atributo 'select' esta seleccionando el atributo 'nombre' como el valor a mostrar. Veamos las tablas de ambos elementos:</parrafo>

<listado titulo="&lt;xsl:template&gt;">
<elemento titulo="match" datos="Define con sintaxis XPath los nodos a los que se debe aplicar este modelo." color="green"/>
<elemento titulo="name" datos="Define un nombre por el cual un elemento 'xsl:call-template' puede invocarlo." color="green"/>
<elemento titulo="mode" datos="Define un nombre con el cual se pueden diferenciar varios modelos a aplicar sobre el mismo nodo." color="green"/>
<elemento titulo="priority" datos="Define la prioridad con un número. Este atributo solo se tendrá en cuenta cuando varios modelos tengan la misma prioridad por defecto." color="green"/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:value-of&gt;">                                                                                               <elemento titulo="select" datos="Define la expresión XPath que se debe evaluar y mostrar."/>
<elemento titulo="disable-output-escaping" datos="Define si se debe deshabilitar la sustitución automática de símbolos reservados. Solo es aplicable si &lt;xsl:output method='html'&gt; o &lt;xsl:output method='xml'&gt;." color="green">
	<subelemento titulo="yes"/>
	<subelemento titulo="no"/>
</elemento>
</listado>

<parrafo>Si procesamos la nueva hoja de estilo obtendremos:</parrafo>

<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?>Biblioteca Municipal
</codigo>

<parrafo>¿Que ha pasado?. Realmente el proceso ha salido bien, pero no esta el listado que esperábamos obtener. Las transformaciones que el procesador XSLT realiza por defecto afectan a elementos que no estén definidos en la hoja de estilo, al definir que se debe hacer con el elemento 'biblioteca' los elementos hijos ya no sufren las transformaciones por defecto, salvo que se defina explícitamente que el contenido del elemento 'biblioteca' debe aparecer:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:template match="biblioteca">
		&lt;xsl:value-of select="@nombre"/>
<nuevo color="white">		&lt;xsl:value-of select="."/></nuevo>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>El contenido del elemento 'biblioteca' incluye todo el contenido entre las etiquetas, lo que incluye los hijos 'libro' y 'revista', el procesador transforma por defecto los elementos hijo mostrando su contenido:</parrafo>

<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?>Biblioteca Municipal
Matemáticas
Historia
Ciencia
OVNI
</codigo>

<parrafo>Ahora supongamos que queremos obtener un archivo de texto plano, es decir sin la declaración XML:</parrafo>


<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<nuevo color="white">	&lt;xsl:output method="text"/></nuevo>
	&lt;xsl:template match="biblioteca">
		&lt;xsl:value-of select="@nombre"/>
		&lt;xsl:value-of select="."/>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Hemos utilizado el elemento 'xsl:output' para definir que tipo de archivo resultante queremos. Este elemento es muy completo e iremos hablando de él a lo largo del mini como.</parrafo>

<listado titulo="&lt;xsl:output&gt;">
<elemento titulo="method" datos="Define el tipo de documento resultante." color="green">
	<subelemento titulo="xml"/>
	<subelemento titulo="html"/>
	<subelemento titulo="text"/>
</elemento>
<elemento titulo="version" datos="Define el valor del atributo 'version' de la declaración XML o HTML en el documento resultante. Solo es aplicable si method='html' o method='xml'." color="green"/>
<elemento titulo="encoding" datos="Define el valor del atributo 'encoding' de la declaración XML en el documento resultante. Solo es aplicable si method='xml'." color="green">
	<subelemento titulo="UTF-8"/>
	<subelemento titulo="ISO-8859-1"/>
	<subelemento titulo="ISO-8859-15"/>
</elemento>
<elemento titulo="omit-xml-declaration" datos="Define si se debe omitir la declaración XML en el documento resultante. Solo es aplicable si method='xml'." color="green">
	<subelemento titulo="yes"/>
	<subelemento titulo="no"/>
</elemento>
<elemento titulo="standalone" datos="Define el valor del atributo 'standalone' de la declaración XML en el documento resultante. Solo es aplicable si method='xml'." color="green">
	<subelemento titulo="yes"/>
	<subelemento titulo="no"/>
</elemento>
<elemento titulo="doctype-public" datos="Define el valor del atributo 'PUBLIC' de la declaración DOCTYPE en el documento resultante. Solo es aplicable si method='html' o method='xml'." color="green"/>
<elemento titulo="doctype-system" datos="Define el valor del atributo 'SYSTEM' de la declaración DOCTYPE en el documento resultante. Solo es aplicable si method='html' o method='xml'." color="green"/>
<elemento titulo="cdata-section-elements" datos="Define un listado de elementos que deben ser escritos como secciones CDATA en el documento resultante. Solo es aplicable si method='xml'." color="green"/>
<elemento titulo="indent" datos="Define si se debe hacer una sangría con las etiquetas en el documento resultante. Solo es aplicable si method='html' o method='xml'." color="green">
	<subelemento titulo="yes"/>
	<subelemento titulo="no"/>
</elemento>
<elemento titulo="media-type" datos="Define el tipo MIME del documento resultante." color="green">
	<subelemento titulo="text/xml"/>
	<subelemento titulo="application/xml"/>
	<subelemento titulo="text/html"/>
	<subelemento titulo="text/xsl"/>
</elemento>
</listado>

<parrafo>Con la hoja de estilo <numcap/>.8 obtenemos el listado que buscábamos:</parrafo>

<codigo>
Biblioteca Municipal
Matemáticas
Historia
Ciencia
OVNI
</codigo>

</capitulo>


<capitulo titulo="Transformaciones: básicas II">

<parrafo>En el anterior capítulo hemos visto como hacer unas simples transformaciones con unos pocos elementos, pero para obtener resultados más interesantes deberemos utilizar más elementos. Pero antes definamos un documento XML más completo:</parrafo>

<codigo tipo="xml">
&lt;?xml version="1.0"?>
&lt;biblioteca nombre="Biblioteca Municipal">
	&lt;datos>
		&lt;publicos>
			&lt;direccion>Calle Mayor, 54&lt;/direccion>
			&lt;telefono>111222333&lt;/telefono>
			&lt;fax>111222000&lt;/fax>
		&lt;/publicos>
		&lt;privados>
			&lt;personal cargo="Oficial Administrativo">Don Pedro&lt;/personal>
			&lt;personal cargo="Técnico Superior de Biblioteca">Don Alberto&lt;/personal>
		&lt;/privados>
	&lt;/datos>
	&lt;documentos>
		&lt;libro paginas="1256">Matemáticas&lt;/libro>
		&lt;libro paginas="345">Historia&lt;/libro>
		&lt;revista paginas="54">Ciencia&lt;/revista>
		&lt;revista paginas="90">OVNI&lt;/revista>
	&lt;/documentos>
&lt;/biblioteca>
</codigo>

<parrafo>En la próxima hoja de estilo vamos a definir varios modelos, de tal modo que unos llamen a otros y poder controlar mejor el resultado.</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="text"/&gt;
	&lt;xsl:template match="biblioteca">
		&lt;xsl:value-of select="@nombre"/&gt;.
<nuevo color="white">		&lt;xsl:apply-templates select="documentos/*"/&gt;</nuevo>
	&lt;/xsl:template>
<nuevo color="white">	&lt;xsl:template match="*">
		&lt;xsl:value-of select="position()"/&gt;. &lt;xsl:value-of select="text()"/&gt;.
	&lt;/xsl:template></nuevo>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>En esta hoja de estilo hay dos modelos: el primero afecta al elemento 'biblioteca' y el segundo a todos los elementos. Por prioridad se procesa el modelo que afecta a 'biblioteca' primero y este con el elemento 'apply-templates' llama a cualquier modelo que afecte a los elementos hijo de 'documentos'.</parrafo>


<listado titulo="&lt;xsl:apply-templates&gt;">
<elemento titulo="select" datos="Define una expresión XPath que selecciona los nodos a los que se debe aplicar los modelos. Si no se define se seleccionan todos los elementos hijos del nodo actual." color="green"/>
<elemento titulo="mode" datos="Define un nombre con el cual sólo permite aplicar elementos 'xsl:template' cuyo atributo 'mode' sea igual." color="green"/>
</listado>

<parrafo>Dentro de 'documentos' existen dos tipos de elementos 'libro' y 'revista', ambos serán procesados con el segundo modelo. Este segundo modelo obtiene la posición del elemento con la función XPath 'position()', escribe un punto y un espacio, muestra el contenido de texto del elemento con la función XPath 'text()' y escribe otro punto. De este modo obtenemos este listado:</parrafo>

<codigo>
Biblioteca Municipal.
1. Matemáticas.
2. Historia.
3. Ciencia.
4. OVNI.
</codigo>

<parrafo>Hay otra forma de utilizar modelos y es llamándolos directamente. Vamos a utilizar esta forma para mostrar los datos de la biblioteca al principio del listado.</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="text"/&gt;
	&lt;xsl:template match="biblioteca">
<nuevo color="white">		&lt;xsl:call-template name="titulo"/></nuevo>
		&lt;xsl:apply-templates select="documentos/*"/&gt;
	&lt;/xsl:template>
	&lt;xsl:template match="*">
		&lt;xsl:value-of select="position()"/&gt;. &lt;xsl:value-of select="text()"/&gt;.
	&lt;/xsl:template>
<nuevo color="white">	&lt;xsl:template name="titulo">
		&lt;xsl:value-of select="@nombre"/&gt;.
		Dirección: &lt;xsl:value-of select="datos/publicos/direccion"/&gt;.
		Tlf: &lt;xsl:value-of select="datos/publicos/telefono"/&gt;.
		Fax: &lt;xsl:value-of select="datos/publicos/fax"/&gt;.
	&lt;/xsl:template></nuevo>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Vemos que hemos creado un nuevo modelo, pero este tiene un nombre definido con el atributo 'name'. Cuando en la hoja de estilo aparezca un elemento 'xsl:call-template' con un atributo 'name' con el mismo nombre se procesará su contenido.</parrafo>

<listado titulo="&lt;xsl:call-template&gt;">
<elemento titulo="name" datos="Define un nombre con el cual invoca al elemento 'xsl:template' cuyo atributo 'name' sea igual."/>
</listado>

<parrafo>Este método permite mostrar un contenido concreto en un punto exacto, y simplemente con hacer otra llamada al mismo modelo podemos mostrar el mismo contenido en varias zonas del documento resultante pudiendo ahorrar mucho código.</parrafo>

<codigo>
Biblioteca Municipal.
Dirección: Calle Mayor, 54.
Tlf: 111222333.
Fax: 111222000.
1. Matemáticas.
2. Historia.
3. Ciencia.
4. OVNI.
</codigo>

<parrafo>Añadamos un paréntesis a la lista especificando el número de páginas:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="text"/&gt;
	&lt;xsl:template match="biblioteca">
		&lt;xsl:call-template name="titulo"/&gt;
		&lt;xsl:apply-templates select="documentos/*"/&gt;
	&lt;/xsl:template>
	&lt;xsl:template match="*">
		&lt;xsl:value-of select="position()"/&gt;. &lt;xsl:value-of select="text()"/&gt;.
<nuevo color="white">		(&lt;xsl:value-of select="format-number(@paginas, '#,##0')"/&gt; pags.)</nuevo>
	&lt;/xsl:template>
	&lt;xsl:template name="titulo">
		&lt;xsl:value-of select="@nombre"/&gt;.
		Dirección: &lt;xsl:value-of select="datos/publicos/direccion"/&gt;.
		Tlf: &lt;xsl:value-of select="datos/publicos/telefono"/&gt;.
		Fax: &lt;xsl:value-of select="datos/publicos/fax"/&gt;.
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Hemos añadido una función XSLT 'format-number()' para que nos coloque la puntuación necesaria si el número de paginas es superior a mil. Veamos el resultado:</parrafo>

<codigo>
Biblioteca Municipal.
Dirección: Calle Mayor, 54.
Tlf: 111222333.
Fax: 111222000.
1. Matemáticas.
(1,256 pags.)
2. Historia.
(345 pags.)
3. Ciencia.
(54 pags.)
4. OVNI.
(90 pags.)
</codigo>

<parrafo>Lo ha hecho bien, pero siguiendo la puntuación anglosajona. Además sería más cómodo que el número de teléfono tuviese también algún tipo de formato. Para ello deberemos añadir lo siguiente:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="text"/&gt;
<nuevo color="white">	&lt;xsl:decimal-format grouping-separator="."/&gt;
	&lt;xsl:decimal-format name="tel" grouping-separator="-"/&gt;</nuevo>
	&lt;xsl:template match="biblioteca">
		&lt;xsl:call-template name="titulo"/&gt;
		&lt;xsl:apply-templates select="documentos/*"/&gt;
	&lt;/xsl:template>
	&lt;xsl:template match="*">
		&lt;xsl:value-of select="position()"/&gt;. &lt;xsl:value-of select="text()"/&gt;.
<nuevo color="white">		(&lt;xsl:value-of select="format-number(@paginas, '#.##0')"/&gt; pags.)</nuevo>
	&lt;/xsl:template>
	&lt;xsl:template name="titulo">
		&lt;xsl:value-of select="@nombre"/&gt;.
		Dirección: &lt;xsl:value-of select="datos/publicos/direccion"/&gt;.
<nuevo color="white">		Tlf: &lt;xsl:value-of select="format-number(datos/publicos/telefono, '#-##0', 'tel')"/&gt;.
		Fax: &lt;xsl:value-of select="format-number(datos/publicos/fax, '#-##0', 'tel')"/&gt;.</nuevo>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>En esta hoja de estilo aparecen dos elementos 'xsl:decimal-format', el primero no tiene atributo 'name' con lo cual se convierte en el formato por defecto. El segundo si tiene y sólo se aplicará cuando sea llamado expresamente. En la línea en la que se formatea el número de páginas sólo ha cambiado el patrón, sustituyendo la coma anglosajona por el punto. En las líneas en las que aparecen los números de teléfono se ha añadido la función 'format-number()' con un patrón distinto y utilizando el formato definido por el segundo elemento 'xsl:decimal-format'.</parrafo>

<listado titulo="&lt;xsl:decimal-format&gt;">
<elemento titulo="name" datos="Define un nombre para el formato definido." color="green"/>
<elemento titulo="decimal-separator" datos="Define el separador decimal." color="green">
	<subelemento titulo="."/>
</elemento>
<elemento titulo="grouping-separator" datos="Define el separador de grupos (mil)." color="green">
	<subelemento titulo=","/>
</elemento>
<elemento titulo="infinity" datos="Define el símbolo a utilizar para representar infinito." color="green">
	<subelemento titulo="Infinity"/>
</elemento>
<elemento titulo="minus-sign" datos="Define el signo negativo." color="green">
	<subelemento titulo="-"/>
	<subelemento titulo="#x2D"/>
</elemento>
<elemento titulo="NaN" datos="Define el símbolo a utilizar cuando el valor no es un número." color="green">
	<subelemento titulo="NaN"/>
</elemento>
<elemento titulo="percent" datos="Define el símbolo a utilizar para representar porcentajes." color="green">
	<subelemento titulo="%"/>
</elemento>
<elemento titulo="per-mille" datos="Define el símbolo a utilizar para representar unidades por millar." color="green">
	<subelemento titulo="#x2030"/>
</elemento>
<elemento titulo="zero-digit" datos="Define el símbolo a utilizar en el patrón para representar un dígito, incluyendo los ceros a la izquierda y decimales." color="green">
	<subelemento titulo="0"/>
</elemento>
<elemento titulo="digit" datos="Define el símbolo a utilizar en el patrón para representar un dígito, sin incluir los ceros a la izquierda y decimales." color="green">
	<subelemento titulo="#"/>
</elemento>
<elemento titulo="pattern-separator" datos="Define el símbolo a utilizar en el patrón para separar el subpatrón positivo del negativo." color="green">
	<subelemento titulo=";"/>
</elemento>
</listado>

<parrafo>Veamos el resultado de la transformación:</parrafo>

<codigo>
Biblioteca Municipal.
Dirección: Calle Mayor, 54.
Tlf: 111-222-333.
Fax: 111-222-000.
1. Matemáticas.
(1.256 pags.)
2. Historia.
(345 pags.)
3. Ciencia.
(54 pags.)
4. OVNI.
(90 pags.)
</codigo>


</capitulo>


<capitulo titulo="Transformaciones: copiar y crear">

<parrafo>Hasta ahora hemos visto como extraer y dar formato a cierta información contenida en un archivo XML y mostrarla en un documento de texto plano. Supongamos que se nos pide un documento XML, pero con ciertas modificaciones respecto al original (el mismo que hemos utilizado en el capítulo anterior).</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:template match="biblioteca">
<nuevo color="white">		&lt;xsl:copy/&gt;</nuevo>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Con esta hoja de estilo vamos a copiar el elemento 'biblioteca' utilizando el elemento 'xsl:copy'.</parrafo>

<listado titulo="&lt;xsl:copy&gt;">
<elemento titulo="use-attribute-sets" datos="Define una lista de elementos 'attribute-set' que deben usarse por este elemento." color="green"/>
</listado>

<parrafo>Veamos el resultado:</parrafo>

<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?>&lt;biblioteca/&gt;
</codigo>

<parrafo>Hemos obtenido un documento XML y hemos copiado el elemento 'biblioteca', pero no su contenido. Supongamos que queremos obtener una copia del documento original, pero sin los datos privados.</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:template match="biblioteca">
<nuevo color="white">		&lt;xsl:copy>
			&lt;xsl:copy-of select="datos/publicos"/&gt;
			&lt;xsl:copy-of select="documentos"/&gt;
		&lt;/xsl:copy></nuevo>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Con esta hoja de estilo copiamos el elemento 'biblioteca' y dentro hacemos una copia completa de los elementos que nos interesan con el elemento 'xsl:copy-of'.</parrafo>

<listado titulo="&lt;xsl:copy-of&gt;">
<elemento titulo="select" datos="Define una expresión XPath que selecciona que nodos deben copiarse al documento resultante."/>
</listado>

<parrafo>Aquí tenemos el resultado:</parrafo>

<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?>&lt;biblioteca>&lt;publicos>
&lt;direccion>Calle Mayor, 54&lt;/direccion>
&lt;telefono>111222333&lt;/telefono>
&lt;fax>111222000&lt;/fax>
&lt;/publicos>&lt;documentos>
&lt;libro paginas="1256">Matemáticas&lt;/libro>
&lt;libro paginas="345">Historia&lt;/libro>
&lt;revista paginas="54">Ciencia&lt;/revista>
&lt;revista paginas="90">OVNI&lt;/revista>
&lt;/documentos>&lt;/biblioteca>
</codigo>

<parrafo>Hemos obtenido la copia, pero hay dos pegas. La primera es que la copia no es tan clara como el original (una etiqueta por línea), pero como nos encontramos ante un documento XML esto no influye en absoluto. La segunda es que el elemento 'datos' no se ha copiado. Una posible solución a ambas pegas sería:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<nuevo color="white">	&lt;xsl:output method="xml" indent="yes"/&gt;</nuevo>
	&lt;xsl:template match="biblioteca">
		&lt;xsl:copy>
<nuevo color="white">			&lt;xsl:element name="datos"></nuevo>
				&lt;xsl:copy-of select="datos/publicos"/&gt;
<nuevo color="white">			&lt;/xsl:element></nuevo>
			&lt;xsl:copy-of select="documentos"/&gt;
		&lt;/xsl:copy>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

Lo primero que hemos añadido es un elemento 'xsl:output' definiendo que queremos un documento xml y que haga una sangría con el resultado para poder verlo más claro. Luego utilizamos el elemento 'xsl:element' para crear el elemento 'datos' que nos faltaba.

<listado titulo="&lt;xsl:element&gt;">
<elemento titulo="name" datos="Define el nombre de este elemento."/>
<elemento titulo="namespace" datos="Define la URI del 'namespace' de este elemento." color="green"/>
<elemento titulo="use-attribute-sets" datos="Define una lista de elementos 'attribute-set' que deben usarse por este elemento." color="green"/>
</listado>

<parrafo>Veamos el nuevo resultado:</parrafo>

<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;biblioteca>
&lt;datos>
&lt;publicos>
&lt;direccion>Calle Mayor, 54&lt;/direccion>
&lt;telefono>111222333&lt;/telefono>
&lt;fax>111222000&lt;/fax>
&lt;/publicos>
&lt;/datos>
&lt;documentos>
&lt;libro paginas="1256">Matemáticas&lt;/libro>
&lt;libro paginas="345">Historia&lt;/libro>
&lt;revista paginas="54">Ciencia&lt;/revista>
&lt;revista paginas="90">OVNI&lt;/revista>
&lt;/documentos>
&lt;/biblioteca>
</codigo>

<parrafo>Ya hemos solucionado las dos pegas anteriores, pero ahora que se ve claro nos damos cuenta de que al elemento 'biblioteca' le falta el atributo 'nombre'. Y además deberíamos avisar de que este documento es una copia y que en poco tiempo estará desactualizado.</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="xml" indent="yes"/&gt;
	&lt;xsl:template match="biblioteca">
		&lt;xsl:copy>
<nuevo color="white">			&lt;xsl:attribute name="nombre">
				&lt;xsl:value-of select="@nombre"/&gt;
				&lt;xsl:text> (Listado de 29-2-2002)&lt;/xsl:text>
			&lt;/xsl:attribute></nuevo>
			&lt;xsl:element name="datos">
				&lt;xsl:copy-of select="datos/publicos"/&gt;
			&lt;/xsl:element>
<nuevo color="white">			&lt;xsl:comment>Atención!!! Listado de 29-2-2002&lt;/xsl:comment></nuevo>
			&lt;xsl:copy-of select="documentos"/&gt;
		&lt;/xsl:copy>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Para añadir el atributo con el nombre de la biblioteca utilizamos el elemento 'xsl:attribute' y en su interior obtenemos con 'xsl:value-of' el nombre y le añadimos información extra con el elemento 'xsl:text'. Hasta ahora hemos añadido texto directamente a la hoja, pero para tener mayor control es preferible incluirlo dentro de un elemento 'xsl:text'. Por ultimo, hemos añadido una comentario con el elemento 'xsl:comment'.</parrafo>

<listado titulo="&lt;xsl:attribute&gt;">
<elemento titulo="name" datos="Define el nombre de este atributo."/>
<elemento titulo="namespace" datos="Define la URI del 'namespace' de este atributo." color="green"/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:text&gt;">
<elemento titulo="disable-output-escaping" datos="Define si se debe deshabilitar la sustitución automática de símbolos reservados. Solo es aplicable si &lt;xsl:output method='html'&gt; o &lt;xsl:output method='xml'&gt;." color="green">
	<subelemento titulo="yes"/>
	<subelemento titulo="no"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:comment&gt;">
<elemento titulo="SIN ATRIBUTOS" color="red"/>
</listado>

<parrafo>Veamos el resultado final:</parrafo>

<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;biblioteca nombre="Biblioteca Municipal (Listado de 29-2-2002)">
&lt;datos>
&lt;publicos>
&lt;direccion>Calle Mayor, 54&lt;/direccion>
&lt;telefono>111222333&lt;/telefono>
&lt;fax>111222000&lt;/fax>
&lt;/publicos>
&lt;/datos>
&lt;!--Atención!!! Listado de 29-2-2002-->
&lt;documentos>
&lt;libro paginas="1256">Matemáticas&lt;/libro>
&lt;libro paginas="345">Historia&lt;/libro>
&lt;revista paginas="54">Ciencia&lt;/revista>
&lt;revista paginas="90">OVNI&lt;/revista>
&lt;/documentos>
&lt;/biblioteca>
</codigo>

<parrafo>El último elemento de este capítulo es 'xsl:processing-instruction' el cual simplemente define un nombre y un contenido, y los muestra una vez transformado entre '&lt;? ... ?>'.</parrafo>

<listado titulo="&lt;xsl:processing-instruction&gt;">
<elemento titulo="name" datos="Define el nombre de esta instrucción."/>
</listado>

</capitulo>


<capitulo titulo="Transformaciones: programar">

<parrafo>En este capítulo vamos a definir elementos que nos permitan definir condiciones y que hacer en cada caso. Vamos a definir un documento XML que contiene los datos de préstamo de los libros:</parrafo>

<codigo tipo="xml">
&lt;?xml version="1.0"?>
&lt;prestamo hoy="10-03-2002">
	&lt;usuario u_id="u00432">
		&lt;prestado fecha="09-03-2002" doc_id="doc00123"/&gt;
		&lt;prestado fecha="10-03-2002" doc_id="doc01007"/&gt;
	&lt;/usuario>
	&lt;usuario u_id="u03406">
		&lt;prestado fecha="02-03-2002" doc_id="doc00978"/&gt;
	&lt;/usuario>
	&lt;restaurador r_id="r00004">
		&lt;prestado fecha="01-03-2002" doc_id="doc00101"/&gt;
		&lt;prestado fecha="03-03-2002" doc_id="doc00775"/&gt;
		&lt;prestado fecha="03-03-2002" doc_id="doc00067"/&gt;
	&lt;/restaurador>
&lt;/prestamo>
</codigo>

<parrafo>Supongamos que queremos que el bibliotecario tenga acceso a estos datos vía pagina html (voy a dar por supuesto un conocimiento básico de las etiquetas HTML) y que le señale los prestamos que han superado el periodo máximo (7 días).</parrafo>

<codigo tipo="xsl">
<nuevo color="white">&lt;?xml version="1.0" encoding="ISO-8859-15"?></nuevo>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<nuevo color="white">	&lt;xsl:output method="html" encoding="ISO-8859-15"/&gt;</nuevo>
	&lt;xsl:template match="prestamo">
		&lt;html>
		&lt;head>&lt;title>Listado de Préstamo&lt;/title>&lt;/head>
		&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
			&lt;xsl:apply-templates select="*/prestado"/&gt;
		&lt;/ul>
		&lt;/body>
		&lt;/html>
	&lt;/xsl:template>
	&lt;xsl:template match="prestado">
		&lt;li>
		&lt;xsl:value-of select="@doc_id"/&gt;
		&lt;xsl:text> lleva &lt;/xsl:text>
		&lt;xsl:value-of select="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')"/&gt;
		&lt;xsl:text> días prestado.&lt;/xsl:text>
<nuevo color="white">		&lt;xsl:if test="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')&amp;gt;7">
			&lt;xsl:text> [Multa]&lt;/xsl:text>
		&lt;/xsl:if></nuevo>
		&lt;/li>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Lo primero que hemos hecho ha sido elegir la codificación 'ISO-8859-15' para no tener problemas con las tildes de nuestro idioma. También hemos definido el documento resultantes como HTML y con la misma codificación. El resto del modelo nos debería resultar familiar, quizás nos asuste un poco "substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')", que simplemente calcula los días que el documento lleva prestado. La función 'substring-before()' selecciona la subcadena anterior a '-', es decir el día. Y lo que hacemos es restar el día del atributo 'hoy' con el día del atributo 'fecha'. Señalar que hemos simplificado el problema asumiendo que el mes y el año son iguales.</parrafo>

<parrafo>La novedad de esta hoja de estilo está en el elemento 'xsl:if' que define una condición en su atributo 'test' y solo cuando se cumple se procesa su contenido. La condición es que lleve más de 7 días prestado, téngase en cuenta que para representar el signo '>' hemos tenido que substituirlo por '&amp;gt;'.</parrafo>

<listado titulo="&lt;xsl:if&gt;">
<elemento titulo="test" datos="Define una condición, si se cumple se procesará el interior del elemento."/>
</listado>

<parrafo>Veamos el resultado:</parrafo>

<codigo>
&lt;html>
	&lt;head>
		&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15">
		&lt;title>Listado de Préstamo&lt;/title>
	&lt;/head>
	&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
			&lt;li>doc00123 lleva 1 días prestado.&lt;/li>
			&lt;li>doc01007 lleva 0 días prestado.&lt;/li>
			&lt;li>doc00978 lleva 8 días prestado. [Multa]&lt;/li>
			&lt;li>doc00101 lleva 9 días prestado. [Multa]&lt;/li>
			&lt;li>doc00775 lleva 7 días prestado.&lt;/li>
			&lt;li>doc00067 lleva 7 días prestado.&lt;/li>
		&lt;/ul>
	&lt;/body>
&lt;/html>
</codigo>

<parrafo>El listado es correcto, pero hay que definir casos especiales para cuando los días sean 0 y 1. Además 'doc00101' esta prestado a un restaurador, ellos no tienen límite de tiempo y no tiene sentido ponerle una multa.</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="html" encoding="ISO-8859-15"/&gt;
	&lt;xsl:template match="prestamo">
		&lt;html>
		&lt;head>&lt;title>Listado de Préstamo&lt;/title>&lt;/head>
		&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
			&lt;xsl:apply-templates select="*/prestado"/&gt;
		&lt;/ul>
		&lt;/body>
		&lt;/html>
	&lt;/xsl:template>
	&lt;xsl:template match="prestado">
		&lt;li>
		&lt;xsl:value-of select="@doc_id"/&gt;
<nuevo color="white">		&lt;xsl:choose>
			&lt;xsl:when test="name(..)='restaurador'">
				&lt;xsl:text> está en restauración.&lt;/xsl:text>
			&lt;/xsl:when>
			&lt;xsl:when test="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')=0">
				&lt;xsl:text> se ha prestado hoy.&lt;/xsl:text>
			&lt;/xsl:when>
			&lt;xsl:when test="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')=1">
				&lt;xsl:text> lleva 1 día prestado.&lt;/xsl:text>
			&lt;/xsl:when>
			&lt;xsl:otherwise></nuevo>
			&lt;xsl:text> lleva &lt;/xsl:text>
			&lt;xsl:value-of select="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')"/&gt;
			&lt;xsl:text> días prestado.&lt;/xsl:text>
			&lt;xsl:if test="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')&amp;gt;7">
				&lt;xsl:text> [Multa]&lt;/xsl:text>
			&lt;/xsl:if>
<nuevo color="white">			&lt;/xsl:otherwise>
		&lt;/xsl:choose></nuevo>
		&lt;/li>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Para definir todos los casos hemos utilizado el elemento 'xsl:choose' que contiene elementos 'xsl:when' con condiciones y un elemento 'xsl:otherwise' en el caso de que no se cumpla ninguna de las condiciones establecidas. El primer elemento 'xsl:when' define que hacer si el elemento padre se llama 'restaurador' y los otros dos son los casos especiales para 0 y 1 días.</parrafo>

<listado titulo="&lt;xsl:choose&gt;">
<elemento titulo="SIN ATRIBUTOS" color="red"/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:when&gt;">
<elemento titulo="test" datos="Define una condición, si es la primera en cumplirse se procesará el interior del elemento."/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:otherwise&gt;">
<elemento titulo="SIN ATRIBUTOS" color="red"/>
</listado>

<parrafo>El nuevo listado es el siguiente:</parrafo>

<codigo>
&lt;html>
	&lt;head>
		&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15">
		&lt;title>Listado de Préstamo&lt;/title>
	&lt;/head>
	&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
			&lt;li>doc00123 lleva 1 día prestado.&lt;/li>
			&lt;li>doc01007 se ha prestado hoy.&lt;/li>
			&lt;li>doc00978 lleva 8 días prestado. [Multa]&lt;/li>
			&lt;li>doc00101 está en restauración.&lt;/li>
			&lt;li>doc00775 está en restauración.&lt;/li>
			&lt;li>doc00067 está en restauración.&lt;/li>
		&lt;/ul>
	&lt;/body>
&lt;/html>
</codigo>

<parrafo>Ya hemos listado la información de una forma clara, vamos a mostrar otra forma de hacerlo, pero sin utilizar el elemento 'xsl:apply-templates':</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="html" encoding="ISO-8859-15"/&gt;
	&lt;xsl:template match="prestamo">
		&lt;html>
		&lt;head>&lt;title>Listado de Préstamo&lt;/title>&lt;/head>
		&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
<nuevo color="white">		&lt;xsl:for-each select="usuario/prestado"&gt;</nuevo>
			&lt;li>
			&lt;xsl:value-of select="@doc_id"/&gt;
			&lt;xsl:choose>
				&lt;xsl:when test="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')=0">
					&lt;xsl:text> se ha prestado hoy.&lt;/xsl:text>
				&lt;/xsl:when>
				&lt;xsl:when test="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')=1">
					&lt;xsl:text> lleva 1 día prestado.&lt;/xsl:text>
				&lt;/xsl:when>
				&lt;xsl:otherwise>
					&lt;xsl:text> lleva &lt;/xsl:text>
					&lt;xsl:value-of select="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')"/&gt;
					&lt;xsl:text> días prestado.&lt;/xsl:text>
					&lt;xsl:if test="substring-before(/prestamo/@hoy,'-')-substring-before(@fecha,'-')&amp;gt;7">
						&lt;xsl:text> [Multa]&lt;/xsl:text>
					&lt;/xsl:if>
				&lt;/xsl:otherwise>
			&lt;/xsl:choose>
			&lt;/li>
<nuevo color="white">		&lt;/xsl:for-each&gt;</nuevo>
		&lt;/ul>
		&lt;h2>En restauración&lt;/h2>
		&lt;ul>
<nuevo color="white">		&lt;xsl:for-each select="restaurador/prestado"&gt;
			&lt;li>
			&lt;xsl:value-of select="@doc_id"/&gt;
			&lt;/li>
		&lt;/xsl:for-each&gt;</nuevo>
		&lt;/ul>
		&lt;/body>
		&lt;/html>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Como se puede observar el elemento 'xsl:for-each' selecciona un conjunto de nodos y les aplica el modelo que contiene. Hemos separado los libros en restauración del resto, aunque se podría definir una hoja totalmente equivalente a la anterior.</parrafo>

<listado titulo="&lt;xsl:for-each&gt;">
<elemento titulo="select" datos="Define una expresión XPath que selecciona los nodos."/>
</listado>

<parrafo>Veamos el nuevo listado:</parrafo>

<codigo>
&lt;html>
	&lt;head>
		&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15">
		&lt;title>Listado de Préstamo&lt;/title>
	&lt;/head>
	&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
			&lt;li>doc00123 lleva 1 día prestado.&lt;/li>
			&lt;li>doc01007 se ha prestado hoy.&lt;/li>
			&lt;li>doc00978 lleva 8 días prestado. [Multa]&lt;/li>
		&lt;/ul>
		&lt;h2>En restauración&lt;/h2>
		&lt;ul>
			&lt;li>doc00101&lt;/li>
			&lt;li>doc00775&lt;/li>
			&lt;li>doc00067&lt;/li>
		&lt;/ul>
	&lt;/body>
&lt;/html>
</codigo>

<parrafo>Hemos facilitado el trabajo al bibliotecario, pero hemos hecho una trampa: hemos definido a que día estamos en el archivo XML y eso no es correcto, lo lógico es que ese dato se le suministrase a la hoja de estilo cuando sea ejecutada. Para ello precisamos utilizar nuevos elementos.</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="html" encoding="ISO-8859-15"/&gt;
	<nuevo color="white">&lt;xsl:param name="hoy" select="/prestamo/@hoy"/&gt;</nuevo>
	&lt;xsl:template match="prestamo">
		<nuevo color="white">&lt;xsl:param name="dia_hoy" select="substring-before($hoy,'-')"/&gt;</nuevo>
		&lt;html>
		&lt;head>&lt;title>Listado de Préstamo&lt;/title>&lt;/head>
		&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
		&lt;xsl:for-each select="usuario/prestado">
<nuevo color="white">			&lt;xsl:variable name="dias" select="$dia_hoy - substring-before(@fecha,'-')"/&gt;</nuevo>
			&lt;li>
			&lt;xsl:value-of select="@doc_id"/&gt;
			&lt;xsl:choose>
				&lt;xsl:when test="<nuevo color="white">$dias</nuevo>=0">
					&lt;xsl:text> se ha prestado hoy.&lt;/xsl:text>
				&lt;/xsl:when>
				&lt;xsl:when test="<nuevo color="white">$dias</nuevo>=1">
					&lt;xsl:text> lleva 1 día prestado.&lt;/xsl:text>
				&lt;/xsl:when>
				&lt;xsl:otherwise>
					&lt;xsl:text> lleva &lt;/xsl:text>
					&lt;xsl:value-of select="<nuevo color="white">$dias</nuevo>"/&gt;
					&lt;xsl:text> días prestado.&lt;/xsl:text>
					&lt;xsl:if test="<nuevo color="white">$dias</nuevo>&amp;gt;7">
						&lt;xsl:text> [Multa]&lt;/xsl:text>
					&lt;/xsl:if>
				&lt;/xsl:otherwise>
			&lt;/xsl:choose>
			&lt;/li>
		&lt;/xsl:for-each>
		&lt;/ul>
		&lt;h2>En restauración&lt;/h2>
		&lt;ul>
		&lt;xsl:for-each select="restaurador/prestado">
			&lt;li>
			&lt;xsl:value-of select="@doc_id"/&gt;
			&lt;/li>
		&lt;/xsl:for-each>
		&lt;/ul>
		&lt;/body>
		&lt;/html>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Esta hoja de estilo es bastante más clara que la anterior y se debe a la utilización de '$hoy', '$dia_hoy' y '$dias' que han disminuido considerablemente la longitud de las lineas. Hemos definido dos nuevos elementos 'xsl:param' y 'xsl:variable'. Ambos guardan un valor que puede obtenerse añadiendo un signo $ delante del nombre del elemento, pero son diferentes.</parrafo>

<parrafo>El primer elemento 'xsl:param' que definimos tiene un atributo 'name' con el valor 'hoy', lo hemos definido al principio de la hoja de estilo, fuera de cualquier modelo, por lo tanto es un parámetro global, es decir se puede invocar con '$hoy' en cualquier punto de la hoja de estilo. Este elemento tiene un atributo 'select' que señala al atributo 'hoy' del elemento 'prestamo' y ese será su valor por defecto, salvo que se le asigne uno desde el exterior. El proceso de asignar a un parámetro un valor desde fuera de la hoja de estilo depende de cada procesador, por lo que tendrá que consultar la documentación de su procesador XSLT.</parrafo>

<parrafo>El segundo elemento 'xsl:param' se llama 'dia_hoy' y esta definido al principio del único modelo, por lo tanto es un parámetro local y solo se puede invocar dentro de este modelo. El valor asignado es el resultante de aplicar la función substring-before() al parámetro '$hoy'. Es decir, obtiene el día de hoy.</parrafo>

<parrafo>Por último se define un elemento 'xsl:variable' dentro del elemento 'xsl:for-each' llamado 'dias'. A diferencia con los parámetros las variables pueden ser definidas en cualquier punto, no es necesario definirlas al principio del modelo. Otra diferencia de uso es que mientras que el parámetro siempre va a valer lo mismo a lo largo de toda la transformación, la variable va a cambiar de valor. Esta variable calcula su valor restando al valor de '$dia_hoy' el día de la fecha del elemento 'prestado' actual, es decir calcula el número de dias que prestado por cada libro.</parrafo>

<listado titulo="&lt;xsl:param&gt;">i
<elemento titulo="name" datos="Define el nombre del parámetro."/>
<elemento titulo="select" datos="Define una expresión XPath cuyo valor se asigna al parámetro." color="green"/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:variable&gt;">
<elemento titulo="name" datos="Define el nombre de la variable."/>
<elemento titulo="select" datos="Define una expresión XPath cuyo valor se asigna a la variable." color="green"/>
</listado>

<parrafo>Veamos el listado resultante si le pasamos desde el exterior un valor '20-03-2002' al parámetro 'hoy':</parrafo>

<codigo>
&lt;html>
	&lt;head>
		&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15">
		&lt;title>Listado de Préstamo&lt;/title>
	&lt;/head>
	&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
			&lt;li>doc00123 lleva 11 días prestado. [Multa]&lt;/li>
			&lt;li>doc01007 lleva 10 días prestado. [Multa]&lt;/li>
			&lt;li>doc00978 lleva 18 días prestado. [Multa]&lt;/li>
		&lt;/ul>
		&lt;h2>En restauración&lt;/h2>
		&lt;ul>
			&lt;li>doc00101&lt;/li>
			&lt;li>doc00775&lt;/li>
			&lt;li>doc00067&lt;/li>
		&lt;/ul>
	&lt;/body>
&lt;/html>
</codigo>

<parrafo>La diferencia entre parámetro y variable es difícil de apreciar (yo hasta no escribir este ejemplo no la acababa de entender :-). Mientras que el parámetro es un valor fijo, la variable define una especie de función que se aplica en un punto concreto. A primera vista puede parecer que la variable es mucho más potente que el parámetro, en el ejemplo anterior es sencillo sustituir los dos elementos 'xsl:param' por 'xsl:variable', pero perderíamos la posibilidad de definir un valor desde fuera de la hoja de estilo, porque solo un elemento 'xsl:param' puede recoger un valor definido exteriormente. Tampoco podemos sustituir el elemento 'xsl:variable' por otro 'xsl:param', porque necesitamos definirlo dentro del elemento 'xsl:for-each' y los parámetros deben ser definidos al principio. Pero si podemos atacar el problema de otra forma:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="html" encoding="ISO-8859-15"/&gt;
	&lt;xsl:param name="hoy" select="/prestamo/@hoy"/&gt;
	&lt;xsl:template match="prestamo">
		&lt;html>
		&lt;head>&lt;title>Listado de Préstamo&lt;/title>&lt;/head>
		&lt;body>
		&lt;h2>Listado de Préstamo&lt;/h2>
		&lt;ul>
		&lt;xsl:apply-templates select="usuario/prestado">
<nuevo color="white">			&lt;xsl:with-param name="dia_hoy" select="substring-before($hoy,'-')"/&gt;</nuevo>
		&lt;/xsl:apply-templates>
		&lt;/ul>
		&lt;h2>En restauración&lt;/h2>
		&lt;ul>
		&lt;xsl:for-each select="restaurador/prestado">
			&lt;li>
			&lt;xsl:value-of select="@doc_id"/&gt;
			&lt;/li>
		&lt;/xsl:for-each>
		&lt;/ul>
		&lt;/body>
		&lt;/html>
	&lt;/xsl:template>
	&lt;xsl:template match="usuario/prestado">
<nuevo color="white">		&lt;xsl:param name="dia_hoy"/&gt;
		&lt;xsl:param name="dias" select="$dia_hoy - substring-before(@fecha,'-')"/&gt;</nuevo>
		&lt;li>
		&lt;xsl:value-of select="@doc_id"/&gt;
		&lt;xsl:choose>
			&lt;xsl:when test="$dias=0">
				&lt;xsl:text> se ha prestado hoy.&lt;/xsl:text>
			&lt;/xsl:when>
			&lt;xsl:when test="$dias=1">
				&lt;xsl:text> lleva 1 día prestado.&lt;/xsl:text>
			&lt;/xsl:when>
			&lt;xsl:otherwise>
				&lt;xsl:text> lleva &lt;/xsl:text>
				&lt;xsl:value-of select="$dias"/&gt;
				&lt;xsl:text> días prestado.&lt;/xsl:text>
				&lt;xsl:if test="$dias&amp;gt;7">
					&lt;xsl:text> [Multa]&lt;/xsl:text>
				&lt;/xsl:if>
			&lt;/xsl:otherwise>
		&lt;/xsl:choose>
		&lt;/li>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Con la ayuda del elemento 'xsl:with-param' la potencia de los parámetros aumenta de manera sustancial, nos permite pasar un parámetro de un modelo a otro. Para ello deberemos definir con elementos 'xsl:with-param' en el modelo origen que parámetros y con que valor los queremos pasar, y en el modelo destino con elementos 'xsl:param' deberemos definir los parámetros que se esperan recibir. Se debe tener en cuenta que los elementos 'xsl:with-param' sólo se pueden definir dentro de elementos 'xsl:apply-templates' y 'xsl:call-template'.</parrafo>

<listado titulo="&lt;xsl:with-param&gt;">
<elemento titulo="name" datos="Define el nombre del parámetro."/>
<elemento titulo="select" datos="Define una expresión XPath cuyo valor se asigna al parámetro." color="green"/>
</listado>

<parrafo>Las dos últimas hojas de estilo son equivalentes por lo cual obtienen el mismo documento resultante.</parrafo>

</capitulo>


<capitulo titulo="Transformaciones: relacionar y ordenar">

<parrafo>Hemos hecho un buen trabajo en el capítulo anterior, pero aun se puede mejorar. El pobre bibliotecario va a tener que buscar que documento corresponde a 'doc00978' y a quien tiene que multar. Vamos a seguir modificando el documento XML del capítulo anterior, pero vamos a tener acceso a otros dos documentos XML:</parrafo>

<parrafo>'personas.xml':</parrafo>

<codigo tipo="xml">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;personas>
	&lt;usuario nombre="Silvia" tlf="444888000" u_id="u00432"/&gt;
	&lt;usuario nombre="Mónica" tlf="123123321" u_id="u03406"/&gt;
	&lt;restaurador nombre="Irene" tlf="883366000" r_id="r00004"/&gt;
&lt;/personas>
</codigo>

<parrafo>'documentos.xml':</parrafo>

<codigo tipo="xml">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;documentos>
	&lt;doc titulo="Historia vol. 10" isbn="1234567890" doc_id="doc00123"/&gt;
	&lt;doc titulo="Filosofía del ladrón" isbn="5676543789" doc_id="doc01007"/&gt;
	&lt;doc titulo="La verdad sin fundamento" isbn="2341728340" doc_id="doc00978"/&gt;
	&lt;doc titulo="Historia vol. 2" isbn="6638299624" doc_id="doc00101"/&gt;
	&lt;doc titulo="Daños colaterales" isbn="3628840271" doc_id="doc00775"/&gt;
	&lt;doc titulo="Prehistoria en imágenes" isbn="0019374826" doc_id="doc00067"/&gt;
&lt;/documentos>
</codigo>

<parrafo>Supongamos que se nos vuelve a pedir el resultado en archivos de texto plano:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="text" encoding="ISO-8859-15"/&gt;
	&lt;xsl:param name="hoy" select="/prestamo/@hoy"/&gt;
	&lt;xsl:param name="salto">&lt;xsl:text>
&lt;/xsl:text>&lt;/xsl:param>
<nuevo color="white">	&lt;xsl:param name="documentos" select="document('documentos.xml')/documentos/doc"/&gt;
	&lt;xsl:param name="personas" select="document('personas.xml')/personas"/&gt;</nuevo>
	&lt;xsl:template match="prestamo">
		&lt;xsl:text>Listado de Préstamo&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
		&lt;xsl:apply-templates select="usuario/prestado">
			&lt;xsl:with-param name="dia_hoy" select="substring-before($hoy,'-')"/&gt;
		&lt;/xsl:apply-templates>
		&lt;xsl:text>En restauración&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
		&lt;xsl:for-each select="restaurador/prestado">
			&lt;xsl:text>* "&lt;/xsl:text>
<nuevo color="white">			&lt;xsl:value-of select="$documentos[@doc_id=current()/@doc_id]/@titulo"/&gt;</nuevo>
			&lt;xsl:text>" por &lt;/xsl:text>
<nuevo color="white">			&lt;xsl:value-of select="$personas/restaurador[@r_id=current()/../@r_id]/@nombre"/&gt;</nuevo>
			&lt;xsl:text>.&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
		&lt;/xsl:for-each>
	&lt;/xsl:template>
	&lt;xsl:template match="usuario/prestado">
		&lt;xsl:param name="dia_hoy"/&gt;
		&lt;xsl:param name="dias" select="$dia_hoy - substring-before(@fecha,'-')"/&gt;
		&lt;xsl:text>* "&lt;/xsl:text>
<nuevo color="white">		&lt;xsl:value-of select="$documentos[@doc_id=current()/@doc_id]/@titulo"/&gt;</nuevo>
		&lt;xsl:text>"&lt;/xsl:text>
		&lt;xsl:choose>
			&lt;xsl:when test="$dias=0">
				&lt;xsl:text> se ha prestado hoy.&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
			&lt;/xsl:when>
			&lt;xsl:when test="$dias=1">
				&lt;xsl:text> lleva 1 día prestado.&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
			&lt;/xsl:when>
			&lt;xsl:otherwise>
				&lt;xsl:text> lleva &lt;/xsl:text>&lt;xsl:value-of select="$dias"/&gt;
				&lt;xsl:text> días prestado.&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
				&lt;xsl:if test="$dias&amp;gt;7">
					&lt;xsl:text>     [Multa] Responsable: &lt;/xsl:text>
<nuevo color="white">					&lt;xsl:value-of select="$personas/usuario[@u_id=current()/../@u_id]/@nombre"/&gt;</nuevo>
					&lt;xsl:text> tlf:&lt;/xsl:text>
<nuevo color="white">					&lt;xsl:value-of select="$personas/usuario[@u_id=current()/../@u_id]/@tlf"/&gt;</nuevo>
					&lt;xsl:text>.&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
				&lt;/xsl:if>
			&lt;/xsl:otherwise>
		&lt;/xsl:choose>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Hemos definido dos nuevos parámetros que apuntan mediante la función 'document()' a los dos nuevos documentos XML. Después simplemente invocamos los parámetros. La sintaxis XPath necesaria puede parecer complicada, lo que hace es seleccionar un elemento que cumpla unas condiciones definidas en el predicado y luego seleccionamos que dato nos interesa del elemento en cuestión. Veamos el resultado al pasar como parámetro 'hoy' '15-03-2002':</parrafo>

<codigo>
Listado de Préstamo
* "Historia vol. 10" lleva 6 días prestado.
* "Filosofía del ladrón" lleva 5 días prestado.
* "La verdad sin fundamento" lleva 13 días prestado.
     [Multa] Responsable: Mónica tlf:123123321.
En restauración
* "Historia vol. 2" por Irene.
* "Daños colaterales" por Irene.
* "Prehistoria en imágenes" por Irene.
</codigo>

<parrafo>El resultado es el que buscábamos, pero vamos a añadir los códigos 'doc*' en orden alfabético y con algún tipo de numeración:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="text" encoding="ISO-8859-15"/&gt;
	&lt;xsl:param name="hoy" select="/prestamo/@hoy"/&gt;
	&lt;xsl:param name="salto">&lt;xsl:text>
&lt;/xsl:text>&lt;/xsl:param>
	&lt;xsl:param name="documentos" select="document('documentos.xml')/documentos/doc"/&gt;
	&lt;xsl:param name="personas" select="document('personas.xml')/personas"/&gt;
	&lt;xsl:template match="prestamo">
		&lt;xsl:text>Listado de Préstamo&lt;/xsl:text>
		&lt;xsl:value-of select="$salto"/&gt;
		&lt;xsl:apply-templates select="usuario/prestado">
			&lt;xsl:with-param name="dia_hoy" select="substring-before($hoy,'-')"/&gt;
<nuevo color="white">			&lt;xsl:sort select="@doc_id"/&gt;</nuevo>
		&lt;/xsl:apply-templates>
		&lt;xsl:text>En restauración&lt;/xsl:text>
		&lt;xsl:value-of select="$salto"/&gt;
		&lt;xsl:for-each select="restaurador/prestado">
<nuevo color="white">			&lt;xsl:sort select="@doc_id"/&gt;
			&lt;xsl:number value="position()" format="a) "/&gt;</nuevo>
			&lt;xsl:value-of select="@doc_id"/&gt;
			&lt;xsl:text>-> "&lt;/xsl:text>
			&lt;xsl:value-of select="$documentos[@doc_id=current()/@doc_id]/@titulo"/&gt;
			&lt;xsl:text>" por &lt;/xsl:text>
			&lt;xsl:value-of select="$personas/restaurador[@r_id=current()/../@r_id]/@nombre"/&gt;
			&lt;xsl:text>.&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
		&lt;/xsl:for-each>
	&lt;/xsl:template>
	&lt;xsl:template match="usuario/prestado">
		&lt;xsl:param name="dia_hoy"/&gt;
		&lt;xsl:param name="dias" select="$dia_hoy - substring-before(@fecha,'-')"/&gt;
<nuevo color="white">		&lt;xsl:number value="position()" format="1. "/&gt;</nuevo>
		&lt;xsl:value-of select="@doc_id"/&gt;
		&lt;xsl:text>-> "&lt;/xsl:text>
		&lt;xsl:value-of select="$documentos[@doc_id=current()/@doc_id]/@titulo"/&gt;
		&lt;xsl:text>"&lt;/xsl:text>
		&lt;xsl:choose>
			&lt;xsl:when test="$dias=0">
				&lt;xsl:text> se ha prestado hoy.&lt;/xsl:text>
				&lt;xsl:value-of select="$salto"/&gt;
			&lt;/xsl:when>
			&lt;xsl:when test="$dias=1">
				&lt;xsl:text> lleva 1 día prestado.&lt;/xsl:text>
				&lt;xsl:value-of select="$salto"/&gt;
			&lt;/xsl:when>
			&lt;xsl:otherwise>
				&lt;xsl:text> lleva &lt;/xsl:text>
				&lt;xsl:value-of select="$dias"/&gt;
				&lt;xsl:text> días prestado.&lt;/xsl:text>
				&lt;xsl:value-of select="$salto"/&gt;
				&lt;xsl:if test="$dias&gt;7">
					&lt;xsl:text>     [Multa] Responsable: &lt;/xsl:text>
					&lt;xsl:value-of select="$personas/usuario[@u_id=current()/../@u_id]/@nombre"/&gt;
					&lt;xsl:text> tlf:&lt;/xsl:text>
					&lt;xsl:value-of select="$personas/usuario[@u_id=current()/../@u_id]/@tlf"/&gt;
					&lt;xsl:text>.&lt;/xsl:text>&lt;xsl:value-of select="$salto"/&gt;
				&lt;/xsl:if>
			&lt;/xsl:otherwise>
		&lt;/xsl:choose>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Hemos añadido dos nuevos elementos 'xsl:sort' y 'xsl:number'. El primero ordena un conjunto de nodos en función de la característica seleccionada, en este caso el atributo 'doc_id'. Recordar que este elemento sólo puede utilizarse dentro de elementos 'xsl:apply-templates' y 'xsl:for-each'. El elemento 'xsl:number' numera un conjunto de nodos siguiendo un formato, en este caso en particular hemos tenido que utilizar el atributo 'value' y asociarlo a la posición del nodo, de no hacerlo así la numeración tendrá relación con la posición relativa de los nodos dentro del árbol de nodos.</parrafo>

<listado titulo="&lt;xsl:number&gt;">
<elemento titulo="count" datos="Define una expresión XPath que selecciona los nodos a contar." color="green"/>
<elemento titulo="level" datos="Define que niveles se deben contar." color="green">
	<subelemento titulo="single"/>
	<subelemento titulo="multiple"/>
	<subelemento titulo="any"/>
</elemento>
<elemento titulo="from" datos="Define una expresión XPath que indica en que punto debe comenzar la cuenta." color="green"/>
<elemento titulo="value" datos="Define una expresión XPath que será transformada en un número. Es una forma rápida de dar formato a un número." color="green"/>
<elemento titulo="format" datos="Define en que formato se deben mostrar los numero generados." color="green">
	<subelemento titulo="1"/>
	<subelemento titulo="01"/>
	<subelemento titulo="a"/>
	<subelemento titulo="A"/>
	<subelemento titulo="i"/>
	<subelemento titulo="I"/>
</elemento>
<elemento titulo="lang" datos="Define un idioma y por lo tanto el alfabeto a utilizar." color="green"/>
<elemento titulo="letter-value" datos="Define si se debe considerar el formato como alfabético o numérico." color="green">
	<subelemento titulo="alphabetic"/>
	<subelemento titulo="traditional"/>
</elemento>
<elemento titulo="grouping-separator" datos="Define el separador de grupos (mil)." color="green">
	<subelemento titulo=","/>
</elemento>
<elemento titulo="grouping-size" datos="Define el tamaño de los grupos." color="green">
	<subelemento titulo="3"/>
</elemento>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:sort&gt;">
<elemento titulo="select" datos="Define una expresión XPath que selecciona los nodos a ordenar." color="green"/>
<elemento titulo="lang" datos="Define el idioma a utilizar al ordenar." color="green">
	<subelemento titulo="RFC1766" href="http://www.ietf.org/rfc/rfc1766.txt"/>
</elemento>
<elemento titulo="data-type" datos="Define el tipo de datos a ordenar." color="green">
	<subelemento titulo="text"/>
	<subelemento titulo="number"/>
</elemento>
<elemento titulo="order" datos="Define el orden a seguir." color="green">
	<subelemento titulo="ascending"/>
	<subelemento titulo="descending"/>
</elemento>
<elemento titulo="case-order" datos="Define la preferencia al ordenar mayúsculas y minúsculas." color="green">
	<subelemento titulo="upper-first"/>
	<subelemento titulo="lower-first"/>
</elemento>
</listado>

<parrafo>El listado queda así:</parrafo>

<codigo>
Listado de Préstamo
1. doc00123-> "Historia vol. 10" lleva 6 días prestado.
2. doc00978-> "La verdad sin fundamento" lleva 13 días prestado.
     [Multa] Responsable: Mónica tlf:123123321.
3. doc01007-> "Filosofía del ladrón" lleva 5 días prestado.
En restauración
a) doc00067-> "Prehistoria en imágenes" por Irene.
b) doc00101-> "Historia vol. 2" por Irene.
c) doc00775-> "Daños colaterales" por Irene.
</codigo>

<parrafo>Y ahora toca algo más difícil... ordenar los listados por el título de los libros:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0" encoding="ISO-8859-15"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="text" encoding="ISO-8859-15"/&gt;
	&lt;xsl:param name="hoy" select="/prestamo/@hoy"/&gt;
	&lt;xsl:param name="salto">&lt;xsl:text>
&lt;/xsl:text>&lt;/xsl:param>
	&lt;xsl:param name="documentos" select="document('documentos.xml')/documentos/doc"/&gt;
	&lt;xsl:param name="personas" select="document('personas.xml')/personas"/&gt;
<nuevo color="white">	&lt;xsl:key name="p_doc" match="prestamo/*/prestado" use="@doc_id"/&gt;</nuevo>
	&lt;xsl:template match="prestamo">
		&lt;xsl:text>Listado de Préstamo&lt;/xsl:text>
		&lt;xsl:value-of select="$salto"/&gt;
<nuevo color="white">		&lt;xsl:apply-templates select="$documentos[name(key('p_doc',@doc_id)/..)='usuario']"></nuevo>
			&lt;xsl:with-param name="dia_hoy" select="substring-before($hoy,'-')"/&gt;
			&lt;xsl:sort select="@titulo"/&gt;
		&lt;/xsl:apply-templates>
		&lt;xsl:text>En restauración&lt;/xsl:text>
		&lt;xsl:value-of select="$salto"/&gt;
<nuevo color="white">		&lt;xsl:for-each select="$documentos[name(key('p_doc',@doc_id)/..)='restaurador']"></nuevo>
			&lt;xsl:sort select="@titulo"/&gt;
			&lt;xsl:number value="position()" format="a)"/&gt;
			&lt;xsl:text> "&lt;/xsl:text>
			&lt;xsl:value-of select="@titulo"/&gt;
			&lt;xsl:text>" por &lt;/xsl:text>
<nuevo color="white">			&lt;xsl:variable name="r_id" select="key('p_doc',@doc_id)/../@r_id"/&gt;</nuevo>
			&lt;xsl:value-of select="$personas/restaurador[@r_id=$r_id]/@nombre"/&gt;
			&lt;xsl:text>.&lt;/xsl:text>
			&lt;xsl:value-of select="$salto"/&gt;
		&lt;/xsl:for-each>
	&lt;/xsl:template>
	&lt;xsl:template match="doc">
		&lt;xsl:param name="dia_hoy"/&gt;
<nuevo color="white">		&lt;xsl:param name="dias" select="$dia_hoy - substring-before(key('p_doc',@doc_id)/@fecha,'-')"/&gt;</nuevo>
		&lt;xsl:number value="position()" format="1."/&gt;
		&lt;xsl:text> "&lt;/xsl:text>
		&lt;xsl:value-of select="@titulo"/&gt;
		&lt;xsl:text>"&lt;/xsl:text>
		&lt;xsl:choose>
			&lt;xsl:when test="$dias=0">
				&lt;xsl:text> se ha prestado hoy.&lt;/xsl:text>
				&lt;xsl:value-of select="$salto"/&gt;
			&lt;/xsl:when>
			&lt;xsl:when test="$dias=1">
				&lt;xsl:text> lleva 1 día prestado.&lt;/xsl:text>
				&lt;xsl:value-of select="$salto"/&gt;
			&lt;/xsl:when>
			&lt;xsl:otherwise>
				&lt;xsl:text> lleva &lt;/xsl:text>
				&lt;xsl:value-of select="$dias"/&gt;
				&lt;xsl:text> días prestado.&lt;/xsl:text>
				&lt;xsl:value-of select="$salto"/&gt;
				&lt;xsl:if test="$dias&gt;7">
<nuevo color="white">					&lt;xsl:variable name="u_id" select="key('p_doc',@doc_id)/../@u_id"/&gt;</nuevo>
					&lt;xsl:text> [Multa] Responsable: &lt;/xsl:text>
					&lt;xsl:value-of select="$personas/usuario[@u_id=$u_id]/@nombre"/&gt;
					&lt;xsl:text> tlf:&lt;/xsl:text>
					&lt;xsl:value-of select="$personas/usuario[@u_id=$u_id]/@tlf"/&gt;
					&lt;xsl:text>.&lt;/xsl:text>
					&lt;xsl:value-of select="$salto"/&gt;
				&lt;/xsl:if>
			&lt;/xsl:otherwise>
		&lt;/xsl:choose>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Hemos tenido que cambiar la forma de atacar el problema, hasta ahora recorríamos los datos de 'prestamo' y buscábamos referencias en los otros archivos. Ahora en cambio, como queremos ordenar por el título, tenemos que recorrer los datos de 'documentos' y después buscar las referencias en 'prestamo' y en 'personas'. Para poder manejarnos con estas referencias tan complejas utilizamos el elemento 'xsl:key' y la función 'key()'.</parrafo>

<parrafo>El elemento 'xsl:key' genera un índice que facilita la localización directa de un elemento definiendo una de sus características, en este caso hemos hecho un índice de los elementos 'prestado' utilizando su atributo 'doc_id'. De tal manera que en cualquier punto de la hoja de estilo con la función 'key()' podemos obtener información sobre aquel de los elementos cuyo atributo 'doc_id' tiene un valor en concreto. En este ejemplo cada código tiene un único elemento asociado, pero en el caso de que existan más elementos asociados la función 'key()' los devuelve todos.</parrafo>

<listado titulo="&lt;xsl:key&gt;">
<elemento titulo="name" datos="Define un nombre para esta clave."/>
<elemento titulo="match" datos="Define una expresión XPath que selecciona los nodos a ser indexados por esta clave."/>
<elemento titulo="use" datos="Define una expresión XPath que escoge una propiedad de los nodos seleccionados que posteriormente servirá para realizar búsquedas."/>
</listado>

<parrafo>Aquí tenemos el listado final:</parrafo>

<codigo>
Listado de Préstamo
1. "Filosofía del ladrón" lleva 5 días prestado.
2. "Historia vol. 10" lleva 6 días prestado.
3. "La verdad sin fundamento" lleva 13 días prestado.
     [Multa] Responsable: Mónica tlf:123123321.
En restauración
a) "Daños colaterales" por Irene.
b) "Historia vol. 2" por Irene.
c) "Prehistoria en imágenes" por Irene.
</codigo>

</capitulo>


<capitulo titulo="Transformaciones: por partes">

<parrafo>Hemos visto que las hojas de estilo poco a poco empiezan a ser muy complejas y extensas, por ello es importante utilizar elementos que nos permitan definir la hoja por partes y con un poco de planificación crear partes que puedan ser reutilizables.</parrafo>

<codigo tipo="xml">
&lt;?xml version="1.0"?>
&lt;novedades>
	&lt;doc tipo="libro"/&gt;
	&lt;doc tipo="revista"/&gt;
	&lt;doc tipo="cdrom"/&gt;
	&lt;doc tipo="cdrom"/&gt;
&lt;/novedades>
</codigo>

<parrafo>Este documento XML es un listado de nuevas obras de las cuales hay que crear un formulario donde introducir los datos interesantes para cada tipo de obra.</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:output method="xml" indent="yes"/&gt;
	<nuevo color="white">&lt;xsl:attribute-set name="general"></nuevo>
		&lt;xsl:attribute name="doc_id"/&gt;
		&lt;xsl:attribute name="titulo"/&gt;
	<nuevo color="white">&lt;/xsl:attribute-set>
	&lt;xsl:attribute-set name="libro" use-attribute-sets="general"></nuevo>
		&lt;xsl:attribute name="isbn"/&gt;
	<nuevo color="white">&lt;/xsl:attribute-set>
	&lt;xsl:attribute-set name="revista" use-attribute-sets="general"></nuevo>
		&lt;xsl:attribute name="issn"/&gt;
	<nuevo color="white">&lt;/xsl:attribute-set></nuevo>
	&lt;xsl:template match="novedades">
		&lt;xsl:element name="formulario">
		&lt;xsl:for-each select="doc">
			&lt;xsl:choose>
				&lt;xsl:when test="@tipo='libro'">
					<nuevo color="white">&lt;xsl:element name="doc" use-attribute-sets="libro"/&gt;</nuevo>
				&lt;/xsl:when>
				&lt;xsl:when test="@tipo='revista'">
					<nuevo color="white">&lt;xsl:element name="doc" use-attribute-sets="revista"/&gt;</nuevo>
				&lt;/xsl:when>
				&lt;xsl:otherwise>
					<nuevo color="white">&lt;xsl:element name="doc" use-attribute-sets="general"/&gt;</nuevo>
				&lt;/xsl:otherwise>
			&lt;/xsl:choose>
		&lt;/xsl:for-each>
		&lt;/xsl:element>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>En esta hoja de estilo utilizamos elementos 'xsl:attribute-set' para agrupar elementos 'xsl:attribute'. Utilizando el atributo 'use-attribute-sets' en elementos 'xsl:element' o 'xsl:attribute-set', podemos utilizar los grupos de atributos ya creados. De este modo podemos ahorrar mucho código y además cualquier modificación posterior que se quiera realizar es rápida y sencilla.</parrafo>

<listado titulo="&lt;xsl:attribute-set&gt;">
<elemento titulo="name" datos="Define el nombre de este grupo de atributos."/>
<elemento titulo="use-attribute-sets" datos="Define una lista de elementos 'attribute-set' que deben usarse por este grupo de atributos." color="green"/>
</listado>

<parrafo>Veamos el resultado:</parrafo>

<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;formulario>
	&lt;doc doc_id="" titulo="" isbn=""/&gt;
	&lt;doc doc_id="" titulo="" issn=""/&gt;
	&lt;doc doc_id="" titulo=""/&gt;
	&lt;doc doc_id="" titulo=""/&gt;
&lt;/formulario>
</codigo>

<parrafo>Hasta aquí podemos agrupar atributos, pero ahora conozcamos elementos que nos permitan definir hojas de estilo por partes definidas en diferentes archivos.</parrafo>

<parrafo>'pordefecto.xsl':</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:template match="doc">
		&lt;doc tipo="{@tipo}"/&gt;
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>'libro.xsl':</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	&lt;xsl:template match="doc[@tipo='libro']">
		&lt;libro/&gt;
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Veamos como unificar los diversos archivos:</parrafo>

<codigo tipo="xsl">
&lt;?xml version="1.0"?>
&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<nuevo color="white">&lt;xsl:import href="pordefecto.xsl"/&gt;</nuevo>
	&lt;xsl:output method="xml" indent="yes"/&gt;
	&lt;xsl:template match="novedades">
		&lt;formulario>
			&lt;xsl:apply-templates select="doc"/&gt;
		&lt;/formulario>
	&lt;/xsl:template>
	<nuevo color="white">&lt;xsl:include href="libro.xsl"/&gt;</nuevo>
	&lt;xsl:template match="doc[@tipo='revista']">
		<nuevo color="white">&lt;xsl:apply-imports/&gt;</nuevo>
	&lt;/xsl:template>
&lt;/xsl:stylesheet>
</codigo>

<parrafo>Hemos utilizado tres nuevos elementos: el primero, 'xsl:import' que señala una hoja de estilo que se aplicará por defecto, en el caso de que no se especifique alguna transformación; el segundo, 'xsl:include' que permite introducir contenidos de otras hojas de estilo en un punto concreto de la hoja actual; y el tercero, 'xsl:apply-imports' que permite aplicar en este punto en concreto las transformaciones definidas en la hoja importada por encima de cualquier otra transformación que normalmente tiene mayor prioridad.</parrafo>

<listado titulo="&lt;xsl:include&gt;">
<elemento titulo="href" datos="Define la URI de la hoja de estilo a incluir."/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:import&gt;">
<elemento titulo="href" datos="Define la URI de la hoja de estilo a importar."/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:apply-imports&gt;">
<elemento titulo="SIN ATRIBUTOS" color="red"/>
</listado>

<parrafo>Veamos el resultado:</parrafo>

<codigo>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;formulario>
	&lt;libro/&gt;
	&lt;doc tipo="revista"/&gt;
	&lt;doc tipo="cdrom"/&gt;
	&lt;doc tipo="cdrom"/&gt;
&lt;/formulario>
</codigo>

</capitulo>


<capitulo titulo="Transformaciones: especiales">

<parrafo>En este capítulo voy a citar elementos muy especiales cuyo uso es muy específico y normalmente muy poco frecuente.</parrafo>


<parrafo>Los elementos 'xsl:strip-space' y 'xsl:preserve-space' permiten definir que hacer con los espacios sobrantes, en algunos elementos nos interesará eliminarlos y en otros mantenerlos. Como espacios sobrantes nos referimos a una sucesión de espacios, ya estén al principio, final o centro de los contenidos.</parrafo>

<listado titulo="&lt;xsl:strip-space&gt;">
<elemento titulo="elements" datos="Define una lista de elementos a los que se les va a quitar los espacios sobrantes."/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:preserve-space&gt;">
<elemento titulo="elements" datos="Define una lista de elementos a los que no se les va a quitar los espacios sobrantes."/>
</listado>

<parrafo>Un elemento muy especial es 'xsl:namespace-alias', este elemento nos permite utilizar un prefijo para los elementos en la hoja de estilo que tras la transformación se substituirá por otro. El uso más claro para este elemento es para definir hojas de estilo cuyo resultado va a ser otra hoja de estilo y de este modo señalar al procesador XSLT que elementos no debe procesar.</parrafo>

<listado titulo="&lt;xsl:namespace-alias&gt;">
<elemento titulo="stylesheet-prefix" datos="Define el prefijo utilizado en la hoja de estilo para referirse al 'namespace'."/>
<elemento titulo="result-prefix" datos="Define el prefijo que sustituirá al anterior en el documento resultante."/>
</listado>

<parrafo>Por último, voy a citar dos elementos más: 'xsl:fallback' y 'xsl:message'. Ambos son métodos que definen como reaccionar cuando algo no se procesa de la forma esperada. El primer elemento define que hacer en el caso de que un elemento extendido no se encuentre disponible y por ello no se va a poder ejecutar. El segundo permite mandar un mensaje, que nos permitirá descubrir con facilidad donde se ha producido el error o porque se debe detener la transformación.</parrafo>

<listado titulo="&lt;xsl:fallback&gt;">
<elemento titulo="SIN ATRIBUTOS" color="red"/>
</listado>

<parrafo/>

<listado titulo="&lt;xsl:message&gt;">
<elemento titulo="terminate" datos="Define si el procesador XSLT debe detenerse después de mostrar este mensaje." color="green">
	<subelemento titulo="no"/>
	<subelemento titulo="yes"/>
</elemento>
</listado>

</capitulo>


<capitulo titulo="Ejemplos completos">

<parrafo>Como punto final del mini-como voy a señalar 2 aplicaciones, que he generado basándome en esta tecnología, para mostrar la adaptabilidad del XSLT.</parrafo>

<listado titulo="Ejemplos completos">
<elemento titulo="XSLT Mini COMO" datos="Este documento." href="http://xml.utilitas.org/xslt_mini_como.html">
	<subelemento titulo="Archivo XML" href="xslt_mini_como.xml"/>
	<subelemento titulo="Archivo XSL" href="xslt_mini_como.xsl"/>
</elemento>
<elemento titulo="Ecolnet" datos="Diagramas generados dinámicamente." href="http://helvete.escomposlinux.org/ecolnet/"/>
</listado>

</capitulo>

</como>
