Si queremos que se nos cierre la ventana del navegador al ejecutar un evento, podemos crear un webpanel "Close", y llamarlo al momento de querer cerrarla.
El webpanel Close debe tener un textblock con formato HTML con el siguiente código en el evento start:
<script>window.open('','_parent','');window.close();</script>
esto lo que hace es primeramente evitar que te pregunte confirmación al cerrar emulando que se abrió desde otra ventana y luego hace el close.
Esto funciona perfectamente en IE, pero en Mozilla por razones de "seguridad" hay una configuración del navegador que no permite cerrar las ventanas vía scripts.
La manera de cambiar esta configuración es la siguiente:
1) Entramos a la configuración de mozilla poniendo en la barra de direcciones about:config
2) Se va a presentar una advertencia, seguimos adelante
3) Luego filtramos por close y cambiamos el valor de la propiedad dom.allow_scripts_to_close_windows a true
Compartiendo GeneXus y Más...
Siempre tenemos algo para aportar, este blog intenta aportar al entorno, al Uruguay y al mundo ese granito de arena, que en la relatividad de todas las cosas para alguien podría llegar a ser una gran duna.
miércoles, 1 de diciembre de 2010
miércoles, 11 de agosto de 2010
Calculator - User Control
Este control es bastante simple pero pienso que también bastante útil, dado que en nuestras aplicaciones podemos tener una calculadora integrada, que no se cierra mientras navegamos por nuestra aplicación, como si pasa por ejemplo con la calculadora de windows.
A su vez, permite ingresar manualmente la expresión a calcular, lo cual facilita bastante, sobre todo en sistemas de información con muchos cálculos.
Es un lindo chiche y muy fácil de incorporar.
Particularidad
Utilización de una plantilla html
Lo novedoso de este control es que graba el html a generar del control en un archivo de texto, que luego lo levanta desde el javascript y le modifica ciertos parámetros antes de desplegar.
Esto facilitó bastante porque independizó el código html a mostrar del javascript.
Este html eventualmente puede ser personalizado por algún usuario que quiera cambiar el aspecto o cambiar algún aspecto de formato.
Links
GeneXus Gallery
http://marketplace.genexus.com/viewproductversion.aspx?126,4,0,0,
Documentación del Control
http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Calculator+Control,
Clic para Bajar el Control
sábado, 10 de abril de 2010
Postits - User Control
Este es un control que hice, porque me pareció que era un chiche lindo para el usuario final, y ya de paso probaba como era que se hacían controles de usuario en GeneXus, la experiencia fue muy positiva, relamente es una facilidad exelente que brinda la versión nueva de GX.
Para generar este control, junto con la documentación que había disponible, lo que hice fue agarrar uno que ya existía y modificarlo, sacarle todo lo que no servía y agregar las particularidades.
Algunas cosas a tener en cuenta
Linkear Variables y deficiones del control con GeneXus
Al hacer cambios en las definiciones de las variables y propiedades, muchas veces no se refresca eso en la KBy al correr la aplicación las variables linkeadas no se cargaban por lo que el control no funcionaba. Lo que yo hacía era correr el genexus.exe /install varias veces y luego arrastraba nuevamente el control, especificaba, generaba, compilaba y ahí se instanciaban las variables en tiempo de ejecución.
Para detectar si esto funciona bien, es conveniente poner en el javascript un alert que muestre con que vienen cargadas nuestras variables, para descartar que no venga por ahí el problema de que no funcione nuestro control.
Code Snippet
Para que al arrastrar el control, se genere código dentro de los eventos de GeneXus es necesario agregar en el archivo MiControl.control dentro de las acciones una acción con esta forma:
<Action>
<Order>10</Order>
<ActionProperties />
<Data>
//Código a poner en los eventos de GX
</Data>
<ActionType>CodeSnippet</ActionType>
</Action>
Esto no se puede hacer desde el editor de controles, al menos no por ahora.
Links
GeneXus Gallery
http://marketplace.genexus.com/viewproductversion.aspx?117,1,0,0
Documentación en GeneXus Wiki
http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Post-Its+Control,
Clic Aquí para Bajarlo
viernes, 18 de diciembre de 2009
Mucho de XSL
XSL
La utilización de XSL nos ha dado mucha facilidad para la generación de código, ya sea html o cualquier código como puede ser PDF o una trasformación de un SDT a otro, lo que precisemos.
Basándonos como entrada en un XML(Datos) y generando a partir de él lo que se nos ocurra. Independizando los datos de entrada de la presentación o formato de salida.
Primeramente mostraremos una presentación general sobre el uso de XSL, luego algunos ejemplos de cosas generadas con XSL, así como también como utlizarlo para enriquecer nuestras aplicaciones con genexus.
Generalidades sobre el USO de XSL
Qué es?
* XSL : Extensible Stylesheet Languaje
* Es un lenguaje basado en XML que permite la transformación, conversión o formateo de documentos XML
* Es un lenguaje, con sentencias y comandos
* Lo particular es que la sintaxis respeta el formato XML
* Partiendo de una entrada en XML se genera mediante el XSL una salida cualquiera
* Se puede generar por ejemplo: HTML, Javascript, XML, o lo que se nos ocurra
Para qué sirve?
Sirve para realizar transformaciones de documentos XML hacia otros formatos, como puede ser HTML, XML, archivos de texto planos, o lo que se desee
Ventajas
* Podemos independizar los datos de la presentación
* Uso de los SDTs en varios lugares del sistema con distinta forma de mostrarlos y personalizables para cada cliente si fuese necesario
* Podemos generar formatos livianos de presentación y estandarizados
Cómo se usa?
* Dado un XML con un formato específico, se programa un XSL que contemple ese formato y la unión del XML con el XSL, mediante un programa de transformación genera el resultado
* Esta unión se llama transformación por lo que al XML le aplicamos una transformación mediante un XSL y obtenemos por ejemplo un HTML
En GeneXus
* Desde GX podemos usarlo de manera sencilla
* Desde la versión 9.0 agregó el método XSLTApply para las variables del tipo string.
* &HTMLResult = &XML.XSLTApply(&XSLFormateo)
Me sirve?
* A mi mucho!
* Pero eso se evalúa cada vez que tenemos que trabajar con DATOS y mostrarlos
* Deberíamos tener presente esta herramienta
* Da soluciones a problemas que de otra manera generan mucho hardcode o soluciones POCO mantenibles, amigables y personalizables
Conclusión
* Es una herramienta más con bastantes prestaciones
* Muchas veces es muy útil, otras no tanto
* La decisión de cuándo, cómo y para qué lo usan y si lo usan :) es de ustedes
Hola Mundo (bajar)
XML
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml:stylesheet type="text/xsl" href="holamundo.xsl"?>
<saludo>
Hola Mundo!
</saludo>
XSL
<?xml version='1.0' encoding='iso-8859-1'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<STYLE>
.miestilo
{
font-weight : bolder;
font-size: 3.2em;
font-family: arial;
text-align: center;
text-shadow: 3px 3px 7px #111;
v-Align: center;
border-style:groove;
border-width:2px;
border-color:gray;
}
</STYLE>
<body leftMargin="2" rightMargin="2" topMargin="2" bottomMargin="2">
<xsl:apply-templates select="saludo"/>
</body>
</html>
</xsl:template>
<xsl:template match="saludo">
<!-- Tabla principal -->
<table>
<tr>
<td>
<span class="miestilo"><b><xsl:value-of select="."/></b></span>
</td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
Inicio (bajar)
XML
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml:stylesheet type="text/xsl" href="inicio.xsl"?>
<personas>
<persona>
<nombre>Elmas</nombre>
<apellido>Grande</apellido>
<edad>119</edad>
<campeon>SI SI SI!!</campeon>
<cuadro>Peñarol</cuadro>
<cuadroa>Peñarol</cuadroa>
</persona>
<persona>
<nombre>Elhijo</nombre>
<apellido>Desiempre</apellido>
<edad>109</edad>
<campeon>NO NO NO!!</campeon>
<cuadro>Nacional</cuadro>
</persona>
</personas>
XSL
<?xml version='1.0' encoding='iso-8859-1'?>
<xsl:stylesheet
version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<style>
.estilonombre
{
font-weight : bolder;
font-size: 25;
font-family: verdana;
background-color: lightgray;
}
.etiqueta
{
font-weight : bolder;
}
.estilocuadro
{
font-weight : bolder;
font-size: 25;
font-family: arial;
color: white;
background-image:url('penarol.png');
text-align: center;
v-Align: center;
border-style:groove;
border-width:2px;
border-color:gray;
}
.estilotabla
{
border-style:groove;
border-width:2px;
border-color:gray;
}
</style>
<body leftMargin="2" rightMargin="2" topMargin="2" bottomMargin="2">
<xsl:apply-templates select="personas"/>
</body>
</html>
</xsl:template>
<xsl:template match="personas">
<xsl:apply-templates select="persona"/>
</xsl:template>
<xsl:template match="persona">
<!-- Tabla principal -->
<table class="estilotabla">
<tbody>
<tr>
<td rowspan="2">
<xsl:choose>
<xsl:when test="cuadro/text()='Peñarol'">
<img src="penarol.jpeg"/>
</xsl:when>
<xsl:when test="cuadro/text()='Nacional'">
<img src="nacional.jpeg"/>
</xsl:when>
</xsl:choose>
</td>
<td>
<table>
<tr>
<td>
<xsl:apply-templates select="nombre"/>
</td>
<td>
<xsl:apply-templates select="apellido"/>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>
<span class="etiqueta">Edad:</span>
</td>
<td>
<xsl:apply-templates select="edad"/>
<xsl:if test="edad/text()<=25">
<span>Un Pibe! (<b>las masitas?</b>)</span>
</xsl:if>
</td>
</tr>
<tr>
<td>
<span class="etiqueta">Campeón:</span>
</td>
<td>
<xsl:apply-templates select="campeon"/>
</td>
</tr>
<tr>
<td>
<span class="etiqueta">El corazón:</span>
</td>
<td>
<xsl:apply-templates select="cuadro"/>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</xsl:template>
<xsl:template match="nombre">
<span class="estilonombre"><xsl:value-of select="."/></span>
</xsl:template>
<xsl:template match="apellido">
<span class="estilonombre"><xsl:value-of select="."/></span>
</xsl:template>
<xsl:template match="edad">
<span><xsl:value-of select="."/></span>
</xsl:template>
<xsl:template match="campeon">
<span><xsl:value-of select="."/></span>
</xsl:template>
<xsl:template match="cuadro">
<span class="estilocuadro"><xsl:value-of select="."/></span>
</xsl:template>
</xsl:stylesheet>
Ejemplos de HTML Generados con XSL
Menú desplegable de Acciones (bajar)
Historia de Expediente (bajar)
Deudas (bajar)

Categorización en Grid (bajar)
Exportacion a Excel (bajar)
(genera un html que se abre con excel)
Registro estructurado en Bandeja de Entrada (bajar)
Alertas (bajar)
Ejemplo de Arbol de Categorías de Materiales (bajar)
En este ejemplo, a partir de un xml generado recursivamente con un procedimiento genexus, utilizando un SDT, cuya definición mostraremos más adelante, obtenemos un html con estructura de árbol, colapsable por nodos. La intención al mostrar este ejemplo es ver como podemos independizar los datos de la visualización de manera muy sencilla. A su vez, utilizando javascript podemos permitir acciones y enriquecer la presentación.
XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml:stylesheet type="text/xsl" href="categorias.xsl"?>
<SDTCategoriasArbol >
<Categorias>
<Categoria>
<Codigo>5</Codigo>
<Descripcion>Azulejos</Descripcion>
<Nivel>1</Nivel>
<Materiales>
<Material>
<Codigo>3</Codigo>
<Descripcion>Material 1</Descripcion>
<Nivel>2</Nivel>
</Material>
<Material>
<Codigo>4</Codigo>
<Descripcion>nuevo material</Descripcion>
<Nivel>2</Nivel>
</Material>
</Materiales>
</Categoria>
<Categoria>
<Codigo>9</Codigo>
<Descripcion>Material de Obra</Descripcion>
<Nivel>1</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>4</Codigo>
<Descripcion>Pisos</Descripcion>
<Nivel>2</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>1</Codigo>
<Descripcion>Madera</Descripcion>
<Nivel>3</Nivel>
</Categoria>
<Categoria>
<Codigo>3</Codigo>
<Descripcion>Cerámicas</Descripcion>
<Nivel>3</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>12</Codigo>
<Descripcion>Alto tránsito</Descripcion>
<Nivel>4</Nivel>
</Categoria>
<Categoria>
<Codigo>13</Codigo>
<Descripcion>Bajo trásito</Descripcion>
<Nivel>4</Nivel>
</Categoria>
</Categorias>
</Categorias>
</Categoria>
</Categorias>
</Categorias>
</Categoria>
</Categorias>
</Categorias>
<Materiales>
<Material>
<Codigo>5</Codigo>
<Descripcion>Porland</Descripcion>
<Nivel>2</Nivel>
</Material>
</Materiales>
</Categoria>
<Categoria>
<Codigo>6</Codigo>
<Descripcion>Medidas</Descripcion>
<Nivel>1</Nivel>
<Materiales>
</Materiales>
</Categoria>
<Categoria>
<Codigo>7</Codigo>
<Descripcion>Pinturas</Descripcion>
<Nivel>1</Nivel>
<Materiales>
</Materiales>
</Categoria>
<Categoria>
<Codigo>10</Codigo>
<Descripcion>Sanitaria</Descripcion>
<Nivel>1</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>8</Codigo>
<Descripcion>Caños</Descripcion>
<Nivel>2</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>2</Codigo>
<Descripcion>Hierro</Descripcion>
<Nivel>3</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>11</Codigo>
<Descripcion>Alta Calidad</Descripcion>
<Nivel>4</Nivel>
</Categoria>
</Categorias>
</Categorias>
</Categoria>
</Categorias>
</Categorias>
</Categoria>
</Categorias>
</Categorias>
<Materiales>
</Materiales>
</Categoria>
</Categorias>
</SDTCategoriasArbol>
XSL
***********Código***********
<?xml version='1.0' encoding='iso-8859-1'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<script type="text/javascript" src="categorias.js"></script>
<style>
.Titulo
{
color: #977659;
font-family: Verdana;
font-size: 13pt;
font-style: normal;
font-variant: normal;
font-weight:bold;
text-decoration: none;
text-shadow: 2px 2px 4px #4AB7D7;
cursor:pointer;
}
.Categoria
{
color: #087184;
font-family: Verdana;
font-size: 10pt;
font-style: normal;
font-variant: normal;
font-weight:bold;
text-decoration: none;
text-shadow: 2px 2px 4px #4AB7D7;
cursor:pointer;
}
.Material
{
color: #977659;
font-family: Verdana;
font-size: 10pt;
font-style: normal;
font-variant: normal;
font-weight:bold;
text-decoration: none;
text-shadow: 2px 2px 4px #4AB7D7;
cursor:pointer;
}
</style>
</head>
<body>
<xsl:apply-templates select="SDTCategoriasArbol"/>
</body>
</html>
</xsl:template>
<xsl:template match="SDTCategoriasArbol">
<table align="left" cellpadding="0" cellspacing="0">
<tr>
<td>
<span class="Titulo">Materiales por Categoría</span>
</td>
</tr>
<tr height="20px">
<td>
</td>
</tr>
<tr>
<xsl:apply-templates select="Categorias"/>
</tr>
</table>
</xsl:template>
<xsl:template match="Categorias">
<xsl:apply-templates select="Categoria"/>
</xsl:template>
<xsl:template match="Categoria">
<tr>
<td>
<xsl:attribute name="style">
padding-left:<xsl:value-of select="Nivel/."/>0;
</xsl:attribute>
<table align="left" cellpadding="0" cellspacing="0">
<tr>
<td>
<xsl:if test="Nivel/. > 1">
<img src="arbollinea.gif"/>
</xsl:if>
<xsl:if test="Nivel/. = 1">
<img src="sig.png"/>
</xsl:if>
</td>
<td valign="top">
<span class="Categoria">
<xsl:attribute name="title">Cód: <xsl:value-of select="Codigo/."/></xsl:attribute>
<xsl:attribute name="style">
<xsl:if test="Nivel/. mod 2 = 0">
color:#379DBA;
</xsl:if>
</xsl:attribute>
<xsl:attribute name="onclick">javascript:verocultar('Id_<xsl:value-of select="Codigo/."/>')</xsl:attribute>
<xsl:value-of select="Descripcion/."/>
</span>
</td>
</tr>
<xsl:if test="Nivel/. = 1">
<tr height="5px">
<td>
</td>
<td>
</td>
</tr>
</xsl:if>
<tr>
<td>
</td>
<td>
<div>
<xsl:attribute name="style">visibility:visible;display:inline;position:relative;</xsl:attribute>
<xsl:attribute name="id">Id_<xsl:value-of select="Codigo/."/></xsl:attribute>
<table align="left" cellpadding="0" cellspacing="0" >
<xsl:apply-templates select="Categorias/Categorias"/>
<xsl:apply-templates select="Materiales"/>
</table>
</div>
</td>
</tr>
</table>
</td>
</tr>
</xsl:template>
<xsl:template match="Materiales">
<xsl:apply-templates select="Material"/>
</xsl:template>
<xsl:template match="Material">
<tr>
<td>
<xsl:attribute name="style">
padding-left:<xsl:value-of select="Nivel/."/>0;
</xsl:attribute>
<table align="left" cellpadding="0" cellspacing="0">
<tr>
<td>
<xsl:if test="Nivel/. > 1">
<img src="arbollinea.gif"/>
</xsl:if>
<xsl:if test="Nivel/. = 1">
<img src="sig.png"/>
</xsl:if>
</td>
<td valign="top">
<span class="Material">
<xsl:attribute name="title">Cód: <xsl:value-of select="Codigo/."/> (<xsl:value-of select="Unidad/."/>)</xsl:attribute>
<xsl:value-of select="Descripcion/."/>
</span>
</td>
</tr>
<xsl:if test="Nivel/. = 1">
<tr height="5px">
<td>
</td>
<td>
</td>
</tr>
</xsl:if>
<tr>
<td>
</td>
<td>
</td>
</tr>
</table>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
***********Fin Código***********
Obs:
Desde GeneXus como hago?
SDT
Procedimiento Recursivo y sus particularidades
En este ejemplo, el procedimiento genera un mapa con todas las categorías que hay definidas, recursivamente, dado que todas ellas hacen referencias al padre.
El procedimiento principal retorna el nombre del archivo generado (un html) y los errores ocurridos.
Guarda en disco el html para accederlo luego desde la aplicción y también guarda el xml generado (el sdt) con algunas modificaciones. Esto fue una decisión para este caso. En muchos otros casos directamente el procedimiento devuelve en un longvarchar el html generado y se muestra en un webpanel con una variable o textblock con formato html.
Procedimiento Principal ( OCategoriaXML )
Rules
parm(out:&Filename, out:&ErrorMessage );
Source
***********Código***********
&SDTCategorias = new SDTCategoriasArbol()
&SDTCategorias.Categorias.Clear()
for each OCategoriaMatPadre OCategoriaMatDescripcion
where OCategoriaMatPadre = 0
defined by OCategoriaMatDescripcion
&Nivel = 1
&Categoria = new SDTCategoriasArbol.Categoria()
&Categoria.Codigo = OCategoriaMatCodigo
&Categoria.Descripcion = OCategoriaMatDescripcion
&Categoria.Nivel = &Nivel
OCategoriaXMLRecursivo.Call(OCategoriaMatCodigo, &Nivel ,&Categoria )
&Categoria.Materiales.Clear()
for each
defined by OMaterialDescripcion
&Material = new SDTCategoriasArbol.Categoria.Material()
&Material.Codigo = OMaterialCodigo
&Material.Descripcion = OMaterialDescripcion
&Material.Unidad = OUnidadDescripcion
&Material.Nivel = &Nivel + 1
&Categoria.Materiales.Add(&Material )
endfor
&SDTCategorias.Categorias.Add(&Categoria )
endfor
&XMLResult = &SDTCategorias.ToXml()
//Obtengo datos desde par�metros
call(GeoParametrosReportes, &XSLPath ,&ExcelPath ,&ExcelRelativePath ,&NameSpace )
&Respuesta = '<?xml version="1.0" encoding="UTF-8"?>' + &SDTCategorias.ToXml()
&Reemplazar = 'xmlns="' + &NameSpace.Trim() + '"'
&Respuesta = &Respuesta.Replace( &Reemplazar , "")
&HTML = &Respuesta.XSLTApply(&XSLPath.Trim() + 'categorias.xsl')
&Random = Random() * 10000
////////Archivo XML
&File = &PgmName.Trim() + !"-" + &Random.ToString().Trim() + !".xml"
&FilePath = &ExcelPath.Trim() + &File
&Filename = &ExcelRelativePath.Trim() + &File
&XMLWriter.Open(&FilePath )
&XMLWriter.WriteRawText(&SDTCategorias.ToXml() )
&XMLWriter.Close()
////////Archivo HTML
&File = &PgmName.Trim() + !"-" + &Random.ToString().Trim() + !".html"
&FilePath = &ExcelPath.Trim() + &File
&Filename = &ExcelRelativePath.Trim() + &File
&XMLWriter.Open(&FilePath )
&XMLWriter.WriteRawText(&HTML )
&XMLWriter.Close()
***********Fin Código***********
Procedimiento Recursivo ( OCategoriaXMLRecursivo )
Rules
parm(in:OCategoriaMatPadre ,in:&Nivel, inout:&Categoria );
Source
***********Código***********
&NivelActual = &Nivel + 1
for each OCategoriaMatPadre
defined by OCategoriaMatDescripcion
&CategoriaHija = new SDTCategoriasArbol.Categoria()
&CategoriaHija.Codigo = OCategoriaMatCodigo
&CategoriaHija.Descripcion = OCategoriaMatDescripcion
&CategoriaHija.Nivel = &NivelActual
OCategoriaXMLRecursivo.Call(OCategoriaMatCodigo, &NivelActual ,&CategoriaHija )
&Categoria.Categorias.Categorias.Add(&CategoriaHija )
endfor
***********Fin Código***********
JS
***********Código***********
function verocultar(tableID)
{
var tab = document.getElementById(tableID);
if (tab.style.visibility == "hidden")
{
verocultarrec(tab, "show");
}
else
{
verocultarrec(tab, "hide");
}
}
function verocultarrec(tab, op)
{
if (tab.style != null && tab.id != null )
{
if (op == "show")
{
tab.style.position="relative";
tab.style.visibility="visible";
oItems = tab.getElementsByTagName("div");
for (var index = 0; index < oItems.length; index++)
{
oItems[index].style.position="relative";
oItems[index].style.visibility="visible";
}
}
else
{
tab.style.position="absolute";
tab.style.visibility="hidden";
oItems = tab.getElementsByTagName("div");
for (var index = 0; index < oItems.length; index++)
{
oItems[index].style.position="absolute";
oItems[index].style.visibility="hidden";
}
}
}
}
***********Fin Código***********
Cómo se ve en ejecución?
La utilización de XSL nos ha dado mucha facilidad para la generación de código, ya sea html o cualquier código como puede ser PDF o una trasformación de un SDT a otro, lo que precisemos.
Basándonos como entrada en un XML(Datos) y generando a partir de él lo que se nos ocurra. Independizando los datos de entrada de la presentación o formato de salida.
Primeramente mostraremos una presentación general sobre el uso de XSL, luego algunos ejemplos de cosas generadas con XSL, así como también como utlizarlo para enriquecer nuestras aplicaciones con genexus.
Generalidades sobre el USO de XSL
Qué es?
* XSL : Extensible Stylesheet Languaje
* Es un lenguaje basado en XML que permite la transformación, conversión o formateo de documentos XML
* Es un lenguaje, con sentencias y comandos
* Lo particular es que la sintaxis respeta el formato XML
* Partiendo de una entrada en XML se genera mediante el XSL una salida cualquiera
* Se puede generar por ejemplo: HTML, Javascript, XML, o lo que se nos ocurra
Para qué sirve?
Sirve para realizar transformaciones de documentos XML hacia otros formatos, como puede ser HTML, XML, archivos de texto planos, o lo que se desee
Ventajas
* Podemos independizar los datos de la presentación
* Uso de los SDTs en varios lugares del sistema con distinta forma de mostrarlos y personalizables para cada cliente si fuese necesario
* Podemos generar formatos livianos de presentación y estandarizados
Cómo se usa?
* Dado un XML con un formato específico, se programa un XSL que contemple ese formato y la unión del XML con el XSL, mediante un programa de transformación genera el resultado
* Esta unión se llama transformación por lo que al XML le aplicamos una transformación mediante un XSL y obtenemos por ejemplo un HTML
En GeneXus
* Desde GX podemos usarlo de manera sencilla
* Desde la versión 9.0 agregó el método XSLTApply para las variables del tipo string.
* &HTMLResult = &XML.XSLTApply(&XSLFormateo)
Me sirve?
* A mi mucho!
* Pero eso se evalúa cada vez que tenemos que trabajar con DATOS y mostrarlos
* Deberíamos tener presente esta herramienta
* Da soluciones a problemas que de otra manera generan mucho hardcode o soluciones POCO mantenibles, amigables y personalizables
Conclusión
* Es una herramienta más con bastantes prestaciones
* Muchas veces es muy útil, otras no tanto
* La decisión de cuándo, cómo y para qué lo usan y si lo usan :) es de ustedes
Hola Mundo (bajar)
XML
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml:stylesheet type="text/xsl" href="holamundo.xsl"?>
<saludo>
Hola Mundo!
</saludo>
XSL
<?xml version='1.0' encoding='iso-8859-1'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<STYLE>
.miestilo
{
font-weight : bolder;
font-size: 3.2em;
font-family: arial;
text-align: center;
text-shadow: 3px 3px 7px #111;
v-Align: center;
border-style:groove;
border-width:2px;
border-color:gray;
}
</STYLE>
<body leftMargin="2" rightMargin="2" topMargin="2" bottomMargin="2">
<xsl:apply-templates select="saludo"/>
</body>
</html>
</xsl:template>
<xsl:template match="saludo">
<!-- Tabla principal -->
<table>
<tr>
<td>
<span class="miestilo"><b><xsl:value-of select="."/></b></span>
</td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
Inicio (bajar)
XML
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml:stylesheet type="text/xsl" href="inicio.xsl"?>
<personas>
<persona>
<nombre>Elmas</nombre>
<apellido>Grande</apellido>
<edad>119</edad>
<campeon>SI SI SI!!</campeon>
<cuadro>Peñarol</cuadro>
<cuadroa>Peñarol</cuadroa>
</persona>
<persona>
<nombre>Elhijo</nombre>
<apellido>Desiempre</apellido>
<edad>109</edad>
<campeon>NO NO NO!!</campeon>
<cuadro>Nacional</cuadro>
</persona>
</personas>
XSL
<?xml version='1.0' encoding='iso-8859-1'?>
<xsl:stylesheet
version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<style>
.estilonombre
{
font-weight : bolder;
font-size: 25;
font-family: verdana;
background-color: lightgray;
}
.etiqueta
{
font-weight : bolder;
}
.estilocuadro
{
font-weight : bolder;
font-size: 25;
font-family: arial;
color: white;
background-image:url('penarol.png');
text-align: center;
v-Align: center;
border-style:groove;
border-width:2px;
border-color:gray;
}
.estilotabla
{
border-style:groove;
border-width:2px;
border-color:gray;
}
</style>
<body leftMargin="2" rightMargin="2" topMargin="2" bottomMargin="2">
<xsl:apply-templates select="personas"/>
</body>
</html>
</xsl:template>
<xsl:template match="personas">
<xsl:apply-templates select="persona"/>
</xsl:template>
<xsl:template match="persona">
<!-- Tabla principal -->
<table class="estilotabla">
<tbody>
<tr>
<td rowspan="2">
<xsl:choose>
<xsl:when test="cuadro/text()='Peñarol'">
<img src="penarol.jpeg"/>
</xsl:when>
<xsl:when test="cuadro/text()='Nacional'">
<img src="nacional.jpeg"/>
</xsl:when>
</xsl:choose>
</td>
<td>
<table>
<tr>
<td>
<xsl:apply-templates select="nombre"/>
</td>
<td>
<xsl:apply-templates select="apellido"/>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>
<span class="etiqueta">Edad:</span>
</td>
<td>
<xsl:apply-templates select="edad"/>
<xsl:if test="edad/text()<=25">
<span>Un Pibe! (<b>las masitas?</b>)</span>
</xsl:if>
</td>
</tr>
<tr>
<td>
<span class="etiqueta">Campeón:</span>
</td>
<td>
<xsl:apply-templates select="campeon"/>
</td>
</tr>
<tr>
<td>
<span class="etiqueta">El corazón:</span>
</td>
<td>
<xsl:apply-templates select="cuadro"/>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</xsl:template>
<xsl:template match="nombre">
<span class="estilonombre"><xsl:value-of select="."/></span>
</xsl:template>
<xsl:template match="apellido">
<span class="estilonombre"><xsl:value-of select="."/></span>
</xsl:template>
<xsl:template match="edad">
<span><xsl:value-of select="."/></span>
</xsl:template>
<xsl:template match="campeon">
<span><xsl:value-of select="."/></span>
</xsl:template>
<xsl:template match="cuadro">
<span class="estilocuadro"><xsl:value-of select="."/></span>
</xsl:template>
</xsl:stylesheet>
Ejemplos de HTML Generados con XSL
Menú desplegable de Acciones (bajar)
Mapa de Acciones (bajar)
Organigrama (bajar)
Historia de Expediente (bajar)
Deudas (bajar)

Exportacion a Excel (bajar)
(genera un html que se abre con excel)
Registro estructurado en Bandeja de Entrada (bajar)
Alertas (bajar)
Ejemplo de Arbol de Categorías de Materiales (bajar)
En este ejemplo, a partir de un xml generado recursivamente con un procedimiento genexus, utilizando un SDT, cuya definición mostraremos más adelante, obtenemos un html con estructura de árbol, colapsable por nodos. La intención al mostrar este ejemplo es ver como podemos independizar los datos de la visualización de manera muy sencilla. A su vez, utilizando javascript podemos permitir acciones y enriquecer la presentación.
XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml:stylesheet type="text/xsl" href="categorias.xsl"?>
<SDTCategoriasArbol >
<Categorias>
<Categoria>
<Codigo>5</Codigo>
<Descripcion>Azulejos</Descripcion>
<Nivel>1</Nivel>
<Materiales>
<Material>
<Codigo>3</Codigo>
<Descripcion>Material 1</Descripcion>
<Nivel>2</Nivel>
</Material>
<Material>
<Codigo>4</Codigo>
<Descripcion>nuevo material</Descripcion>
<Nivel>2</Nivel>
</Material>
</Materiales>
</Categoria>
<Categoria>
<Codigo>9</Codigo>
<Descripcion>Material de Obra</Descripcion>
<Nivel>1</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>4</Codigo>
<Descripcion>Pisos</Descripcion>
<Nivel>2</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>1</Codigo>
<Descripcion>Madera</Descripcion>
<Nivel>3</Nivel>
</Categoria>
<Categoria>
<Codigo>3</Codigo>
<Descripcion>Cerámicas</Descripcion>
<Nivel>3</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>12</Codigo>
<Descripcion>Alto tránsito</Descripcion>
<Nivel>4</Nivel>
</Categoria>
<Categoria>
<Codigo>13</Codigo>
<Descripcion>Bajo trásito</Descripcion>
<Nivel>4</Nivel>
</Categoria>
</Categorias>
</Categorias>
</Categoria>
</Categorias>
</Categorias>
</Categoria>
</Categorias>
</Categorias>
<Materiales>
<Material>
<Codigo>5</Codigo>
<Descripcion>Porland</Descripcion>
<Nivel>2</Nivel>
</Material>
</Materiales>
</Categoria>
<Categoria>
<Codigo>6</Codigo>
<Descripcion>Medidas</Descripcion>
<Nivel>1</Nivel>
<Materiales>
</Materiales>
</Categoria>
<Categoria>
<Codigo>7</Codigo>
<Descripcion>Pinturas</Descripcion>
<Nivel>1</Nivel>
<Materiales>
</Materiales>
</Categoria>
<Categoria>
<Codigo>10</Codigo>
<Descripcion>Sanitaria</Descripcion>
<Nivel>1</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>8</Codigo>
<Descripcion>Caños</Descripcion>
<Nivel>2</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>2</Codigo>
<Descripcion>Hierro</Descripcion>
<Nivel>3</Nivel>
<Categorias>
<Categorias>
<Categoria>
<Codigo>11</Codigo>
<Descripcion>Alta Calidad</Descripcion>
<Nivel>4</Nivel>
</Categoria>
</Categorias>
</Categorias>
</Categoria>
</Categorias>
</Categorias>
</Categoria>
</Categorias>
</Categorias>
<Materiales>
</Materiales>
</Categoria>
</Categorias>
</SDTCategoriasArbol>
XSL
***********Código***********
<?xml version='1.0' encoding='iso-8859-1'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<script type="text/javascript" src="categorias.js"></script>
<style>
.Titulo
{
color: #977659;
font-family: Verdana;
font-size: 13pt;
font-style: normal;
font-variant: normal;
font-weight:bold;
text-decoration: none;
text-shadow: 2px 2px 4px #4AB7D7;
cursor:pointer;
}
.Categoria
{
color: #087184;
font-family: Verdana;
font-size: 10pt;
font-style: normal;
font-variant: normal;
font-weight:bold;
text-decoration: none;
text-shadow: 2px 2px 4px #4AB7D7;
cursor:pointer;
}
.Material
{
color: #977659;
font-family: Verdana;
font-size: 10pt;
font-style: normal;
font-variant: normal;
font-weight:bold;
text-decoration: none;
text-shadow: 2px 2px 4px #4AB7D7;
cursor:pointer;
}
</style>
</head>
<body>
<xsl:apply-templates select="SDTCategoriasArbol"/>
</body>
</html>
</xsl:template>
<xsl:template match="SDTCategoriasArbol">
<table align="left" cellpadding="0" cellspacing="0">
<tr>
<td>
<span class="Titulo">Materiales por Categoría</span>
</td>
</tr>
<tr height="20px">
<td>
</td>
</tr>
<tr>
<xsl:apply-templates select="Categorias"/>
</tr>
</table>
</xsl:template>
<xsl:template match="Categorias">
<xsl:apply-templates select="Categoria"/>
</xsl:template>
<xsl:template match="Categoria">
<tr>
<td>
<xsl:attribute name="style">
padding-left:<xsl:value-of select="Nivel/."/>0;
</xsl:attribute>
<table align="left" cellpadding="0" cellspacing="0">
<tr>
<td>
<xsl:if test="Nivel/. > 1">
<img src="arbollinea.gif"/>
</xsl:if>
<xsl:if test="Nivel/. = 1">
<img src="sig.png"/>
</xsl:if>
</td>
<td valign="top">
<span class="Categoria">
<xsl:attribute name="title">Cód: <xsl:value-of select="Codigo/."/></xsl:attribute>
<xsl:attribute name="style">
<xsl:if test="Nivel/. mod 2 = 0">
color:#379DBA;
</xsl:if>
</xsl:attribute>
<xsl:attribute name="onclick">javascript:verocultar('Id_<xsl:value-of select="Codigo/."/>')</xsl:attribute>
<xsl:value-of select="Descripcion/."/>
</span>
</td>
</tr>
<xsl:if test="Nivel/. = 1">
<tr height="5px">
<td>
</td>
<td>
</td>
</tr>
</xsl:if>
<tr>
<td>
</td>
<td>
<div>
<xsl:attribute name="style">visibility:visible;display:inline;position:relative;</xsl:attribute>
<xsl:attribute name="id">Id_<xsl:value-of select="Codigo/."/></xsl:attribute>
<table align="left" cellpadding="0" cellspacing="0" >
<xsl:apply-templates select="Categorias/Categorias"/>
<xsl:apply-templates select="Materiales"/>
</table>
</div>
</td>
</tr>
</table>
</td>
</tr>
</xsl:template>
<xsl:template match="Materiales">
<xsl:apply-templates select="Material"/>
</xsl:template>
<xsl:template match="Material">
<tr>
<td>
<xsl:attribute name="style">
padding-left:<xsl:value-of select="Nivel/."/>0;
</xsl:attribute>
<table align="left" cellpadding="0" cellspacing="0">
<tr>
<td>
<xsl:if test="Nivel/. > 1">
<img src="arbollinea.gif"/>
</xsl:if>
<xsl:if test="Nivel/. = 1">
<img src="sig.png"/>
</xsl:if>
</td>
<td valign="top">
<span class="Material">
<xsl:attribute name="title">Cód: <xsl:value-of select="Codigo/."/> (<xsl:value-of select="Unidad/."/>)</xsl:attribute>
<xsl:value-of select="Descripcion/."/>
</span>
</td>
</tr>
<xsl:if test="Nivel/. = 1">
<tr height="5px">
<td>
</td>
<td>
</td>
</tr>
</xsl:if>
<tr>
<td>
</td>
<td>
</td>
</tr>
</table>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
***********Fin Código***********
Obs:
- Se podría también tener un css para la definición de estilos, sería más prolijo y generaría un grado más de independiencia entre datos y presentación.
Desde GeneXus como hago?
SDT
Procedimiento Recursivo y sus particularidades
En este ejemplo, el procedimiento genera un mapa con todas las categorías que hay definidas, recursivamente, dado que todas ellas hacen referencias al padre.
El procedimiento principal retorna el nombre del archivo generado (un html) y los errores ocurridos.
Guarda en disco el html para accederlo luego desde la aplicción y también guarda el xml generado (el sdt) con algunas modificaciones. Esto fue una decisión para este caso. En muchos otros casos directamente el procedimiento devuelve en un longvarchar el html generado y se muestra en un webpanel con una variable o textblock con formato html.
Procedimiento Principal ( OCategoriaXML )
Rules
parm(out:&Filename, out:&ErrorMessage );
Source
***********Código***********
&SDTCategorias = new SDTCategoriasArbol()
&SDTCategorias.Categorias.Clear()
for each OCategoriaMatPadre OCategoriaMatDescripcion
where OCategoriaMatPadre = 0
defined by OCategoriaMatDescripcion
&Nivel = 1
&Categoria = new SDTCategoriasArbol.Categoria()
&Categoria.Codigo = OCategoriaMatCodigo
&Categoria.Descripcion = OCategoriaMatDescripcion
&Categoria.Nivel = &Nivel
OCategoriaXMLRecursivo.Call(OCategoriaMatCodigo, &Nivel ,&Categoria )
&Categoria.Materiales.Clear()
for each
defined by OMaterialDescripcion
&Material = new SDTCategoriasArbol.Categoria.Material()
&Material.Codigo = OMaterialCodigo
&Material.Descripcion = OMaterialDescripcion
&Material.Unidad = OUnidadDescripcion
&Material.Nivel = &Nivel + 1
&Categoria.Materiales.Add(&Material )
endfor
&SDTCategorias.Categorias.Add(&Categoria )
endfor
&XMLResult = &SDTCategorias.ToXml()
//Obtengo datos desde par�metros
call(GeoParametrosReportes, &XSLPath ,&ExcelPath ,&ExcelRelativePath ,&NameSpace )
&Respuesta = '<?xml version="1.0" encoding="UTF-8"?>' + &SDTCategorias.ToXml()
&Reemplazar = 'xmlns="' + &NameSpace.Trim() + '"'
&Respuesta = &Respuesta.Replace( &Reemplazar , "")
&HTML = &Respuesta.XSLTApply(&XSLPath.Trim() + 'categorias.xsl')
&Random = Random() * 10000
////////Archivo XML
&File = &PgmName.Trim() + !"-" + &Random.ToString().Trim() + !".xml"
&FilePath = &ExcelPath.Trim() + &File
&Filename = &ExcelRelativePath.Trim() + &File
&XMLWriter.Open(&FilePath )
&XMLWriter.WriteRawText(&SDTCategorias.ToXml() )
&XMLWriter.Close()
////////Archivo HTML
&File = &PgmName.Trim() + !"-" + &Random.ToString().Trim() + !".html"
&FilePath = &ExcelPath.Trim() + &File
&Filename = &ExcelRelativePath.Trim() + &File
&XMLWriter.Open(&FilePath )
&XMLWriter.WriteRawText(&HTML )
&XMLWriter.Close()
***********Fin Código***********
Procedimiento Recursivo ( OCategoriaXMLRecursivo )
Rules
parm(in:OCategoriaMatPadre ,in:&Nivel, inout:&Categoria );
Source
***********Código***********
&NivelActual = &Nivel + 1
for each OCategoriaMatPadre
defined by OCategoriaMatDescripcion
&CategoriaHija = new SDTCategoriasArbol.Categoria()
&CategoriaHija.Codigo = OCategoriaMatCodigo
&CategoriaHija.Descripcion = OCategoriaMatDescripcion
&CategoriaHija.Nivel = &NivelActual
OCategoriaXMLRecursivo.Call(OCategoriaMatCodigo, &NivelActual ,&CategoriaHija )
&Categoria.Categorias.Categorias.Add(&CategoriaHija )
endfor
***********Fin Código***********
JS
***********Código***********
function verocultar(tableID)
{
var tab = document.getElementById(tableID);
if (tab.style.visibility == "hidden")
{
verocultarrec(tab, "show");
}
else
{
verocultarrec(tab, "hide");
}
}
function verocultarrec(tab, op)
{
if (tab.style != null && tab.id != null )
{
if (op == "show")
{
tab.style.position="relative";
tab.style.visibility="visible";
oItems = tab.getElementsByTagName("div");
for (var index = 0; index < oItems.length; index++)
{
oItems[index].style.position="relative";
oItems[index].style.visibility="visible";
}
}
else
{
tab.style.position="absolute";
tab.style.visibility="hidden";
oItems = tab.getElementsByTagName("div");
for (var index = 0; index < oItems.length; index++)
{
oItems[index].style.position="absolute";
oItems[index].style.visibility="hidden";
}
}
}
}
***********Fin Código***********
Cómo se ve en ejecución?
Suscribirse a:
Entradas (Atom)