miércoles, 19 de marzo de 2014

Procesando documentos XPath y XSLT 2.0 desde línea de comandos

Procesado de XPATH 2.0 y XSLT 2.0 con Saxon

Uno de los mayores problemas que tenemos a la hora de crear una hoja de estilos XSLT es cómo depurarla, es decir, cómo saber dónde nos hemos equivocado.
La solución que proponemos es, usando Geany como editor de textos, usar un "compilador" que nos diga dónde hay errores o, incluso, nos procese la hoja de estilos.

Instalando Saxon

Hemos de instalar una de las últimas versiones de Saxon, pues la versión que viene por defecto en las mayores distribuciones Linux sólo soporta XPATH 1.0.
En el caso de usar OpenSuse/CentOS hemos de instalar el paquete saxon9.
En el caso de usar Debian/Ubuntu, hemos de instalar el paquete libsaxonb-java (por ejemplo: sudo apt-get install libsaxonb-java).

Configurando Geany 

Ahora desde el menú Construir-> Establecer Comandos de Construcción de Geany creamos una entrada para "compilar" usando Saxon.

  • En OpenSuse/RedHat: Comando personalizado saxon9 -a:on %f
  • En Debian/Ubuntu: Comando personalizado saxonb-xslt -a %f
De esta manera, pulsando F8 (ó F9, F10... si tenemos más comandos personalizados) "compilamos" el XML. Si no hay errores, obtenemos el documento transformado, en caso contrario, nos indica la línea y columna del error:

Si usas Geany con Windows, puedes usar el comando:
java -cp C:\usr\SaxonHE9\saxon9he.jar net.sf.saxon.Transform %p\%f -a:on
Donde fíjate que el JAR va con la ruta completa y deberás descargarlo de Sourceforge (http://sourceforge.net/projects/saxon/).
También puedes escribir:
java -cp C:\usr\SaxonHE9\saxon9he.jar net.sf.saxon.Transform %p\%f -a:on -o:%p\%e.html 
Para que genere la transformación en un fichero HTML de salida como hacemos en prácticas.

viernes, 7 de marzo de 2014

Un cliente de agregación RSS con jQuery y JSONP

Un lector avanzado de noticias en HTML5 con jQuery, JSONP y YQL 

Con el lector anterior nos surge la pregunta, ¿y si quiero seleccionar el origen de las noticias desde una fuente que lea un formulario?.
Una sencilla solución puede ser usar la biblioteca jQuery y así poder usar el proxy JSON de Yahoo! y nuestra consulta YQL.

Introducción

jQuery es una librería JavaScript para simplificar las tareas de programación, fácil de usar y de aprender.
Su uso está muy extendido, y así, podemos encontrar grandes empresas como Google, Microsoft, etc.
Se puede descargar desde su homepage.
Para usar jQuery en nuestros proyectos Web, hemos de incluirlo en nuestra sección <HEAD>, ya sea en local, de este modo:
<head>
<script src="js/jquery-1.11.0.min.js"></script>
</head>
como en remoto (tirando de una CDN -Content Delivery Network- como Google o Microsoft):
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js">
</script>
</head>

El proxy: JSONP

La filosofía es la misma que comentábamos en el post anterior, donde hacíamos una consulta YQL contra los servidores de Yahoo! y obteníamos como respuesta una cadena JSON con el volcado del fichero XML del la URL del RSS que se le pasaba como argumento.
El problema, ahora, es que vamos a usar jQuery para cargar la cadena JSON, para eso hacemos la llamada $.getJSON.

El código JavaScript

¡Manos a la obra!
Cuando usamos YQL, sus servidores nos devuelve no sólo la cadena JSON, sino un código JavaScript, veamos un ejemplo: vamos a ver qué devuelve el servidor de Yahoo! cuando le hacemos la consulta con wget:
Como en la URL que mando a Yahoo! viene que la función "callback" se llama "mi_funcion", ésta es invocada desde el código que nos devuelven sus servidores, así si miramos el contenido del fichero descargado, veremos lo siguiente:
mi_funcion(
{
   "query":{
      "count":10,
      "created":"2014-03-07T16:04:59Z",
      "lang":"en-US",
      "results":{
         "item":[
            {
               "title":"Una exnovia testifica que Pistorius disparó al aire mientras conducía",
               "link":"http://www.ideal.es/jaen/rc/20140307/deportes/mas-deporte/pistorius_derrumba_jucio_video.xml/pistorius-derrumba-201403071205.html?utm_source=ideal.es&utm_medium=rss&utm_content=ultima-rss&utm_campaign=traffic-rss",
               "description":"",
               "pubDate":"Fri, 07 Mar 2014 15:53:13 GMT",
               "guid":"http://www.ideal.es/jaen/rc/20140307/deportes/mas-deporte/pistorius_derrumba_jucio_video.xml/pistorius-derrumba-201403071205.html?utm_source=ideal.es&utm_medium=rss&utm_content=ultima-rss&utm_campaign=traffic-rss"
            },
            {
               "title":"El Gobierno aprueba la ley que ayudará a salvar empresas viables",
               "link":"http://www.ideal.es/jaen/rc/20140307/economia/gobierno-allana-camino-para-201403070151.html?utm_source=ideal.es&utm_medium=rss&utm_content=ultima-rss&utm_campaign=traffic-rss",
               "description":"",
               "pubDate":"Fri, 07 Mar 2014 15:52:05 GMT",
               "guid":"http://www.ideal.es/jaen/rc/20140307/economia/gobierno-allana-camino-para-201403070151.html?utm_source=ideal.es&utm_medium=rss&utm_content=ultima-rss&utm_campaign=traffic-rss"
            },
....... 

           {
               "title":"Los expertos creen que la nueva ley podría provocar unos 50.000 abortos clandestinos al año",
               "link":"http://www.ideal.es/jaen/rc/20140307/sociedad/nueva-50000-abortos-clandestinos-201403071608.html?utm_source=ideal.es&utm_medium=rss&utm_content=ultima-rss&utm_campaign=traffic-rss",
               "description":"",
               "pubDate":"Fri, 07 Mar 2014 15:25:57 GMT",
               "guid":"http://www.ideal.es/jaen/rc/20140307/sociedad/nueva-50000-abortos-clandestinos-201403071608.html?utm_source=ideal.es&utm_medium=rss&utm_content=ultima-rss&utm_campaign=traffic-rss"
            }
         ]
      }
   }
}
);
De esta manera, la función que usemos puede ser algo parecido a esto:
function cambiaRSS()
{
  var nueva_url = document.getElementById('mi_url').value;
  $.getJSON( "http://query.yahooapis.com/v1/public/yql?q=select * from rss where url=\""+encodeURIComponent(nueva_url)+"\"&format=json&callback=?", function(o) {
 var items = o.query.results.item;  
 var output = '<h2>Útimas noticias</h2>';  
 var no_items=items.length;  
 for(var i=0;i<no_items;i++){  
  var title = items[i].title;  
  var link = items[i].link;  
  var desc = items[i].description;  
  output += "<h4><a href='" + link + "'>"+title+"</a></h4>" + desc + "<hr/>";  
 }  
 document.getElementById('resultados').innerHTML = output;    
 } );
}

Llamada desde el formulario

Para cargar la función, podemos usar un evento "onclick", como se ve en el siguiente ejemplo:

URL del alimentador: 
<input type="text" name="URL" id="mi_url">
<button onclick='cambiaRSS()'> Cambiar! </button>

<div id='resultados'>
Esto será eliminado por los titulares de las noticias.
</div>


martes, 4 de marzo de 2014

Un cliente de noticias en HTML5

Un cliente de agregación RSS en HTML5 con YQL

HTML5 y JavaScript son una potente combinación para hacer ricas aplicaciones móviles o simplemente para colgar en nuestro hosting.
Además, combinadas con los recursos de la red, ofrecen gran flexibilidad y facilidad de uso.
Hoy vamos a ver un ejemplo usando un gran regalo que Yahoo! nos ha hecho a los programadores de aplicaciones móviles y la Web, YQL.

Introducción

Cuando hablamos de hacer un cliente de noticias, que están en XML, y como nuestro cliente va a ser una página Web HTML5, lo primero en lo que pensamos es AJAX.
AJAX es el arte de intercambiar información con un servidor, actualizando partes de una página Web sin recargargar la página entera.
Pero AJAX tiene una gran limitación, y es que, por razones de seguridad, no se pueden intercambiar información con sitios Web diferentes al original donde está alojada la página.
Para solventar este problema, vamos a usar YQL.

¿Qué es YQL?

El Yahoo Query Language, o lenguaje de consulta de Yahoo! es una herramienta para consultar recursos (en nuestro caso documentos XML) como si de base de datos se tratase.
Para nuestro lector RSS, esto no es más que un proxy (un intermediario) con un doble beneficio: 
  • Evitar la limitación de consulta cross-domain de AJAX (no podemos usar una XMLHttpRequest a un sitio Web que no sea donde residen las páginas HTML que lo contienen).
  • Podemos consultar un RSS como si de una base de datos se tratase (ej. "SELECT * FROM ... ").
Fuente: http://developer.yahoo.com/yql/guide/yql-tutorials.html

La consola YQL

En http://developer.yahoo.com/yql/console/ tenemos la consola YQL para probar nuestras consultas.
En nuestro caso vamos a probar cómo generar una cadena JSON a partir del XML generado por el canal RSS de noticias que estemos trabajando.
En nuestro caso vamos a usar el canal de últimas noticias del Diario Ideal de Jaén.
Si abrimos la consola y escribimos el siguiente código:


select * from rss where url="http://www.ideal.es/jaen/rss/feeds/ultima.xml"

Veremos cómo el servicio de Yahoo! nos devuelve la consulta debidamente formateada en JSON (también podríamos pedirle que lo haga en XML).

Preparando el enlace para hacer la consulta

Vamos a hacer un proxy con JSONP.
Preparamos la consulta REST que nos devolverá una cadena JSON:
<script src='http://query.yahooapis.com/v1/public/yql?q=select * from rss where url="http://www.ideal.es/jaen/rss/feeds/ultima.xml"&format=json&callback=mi_funcion'>
</script>
Ahora preparo en mi página un DIV donde aparecerán los resultados y que será el que se reescriba:
<div id='resultados'>
Esto será eliminado por los titulares de las noticias.
</div>

Preparando la función "callback" 

En nuestra cabecera o bien en un fichero "js" aparte, escribimos nuestra función "callback", que es la función que pasamos como interfaz en la consulta anterior.

function mi_funcion(o){  
      var items = o.query.results.item;  
      var output = 'prueba';  
      var no_items=items.length;  
      for(var i=0;i<no_items;i++){  
        var title = items[i].title;  
        var link = items[i].link;  
        var desc = items[i].description;  
        output += "<h4><a href='" + link + "'>"+title+"</a></h4>" + desc + "<hr/>";  
      }  
      // Place news stories in div tag  
      document.getElementById('resultados').innerHTML = output;    
    }  

Si todo ha ido bien, tendremos los titulares y las descripciones de las noticias en nuestra página Web del canal RSS que hemos comentado.