Ho scoperto una cosa curiosa riguardo il sito di Tuttocittá.
Se inviate una query HTTP del tipo
http://www.tuttocitta.it/tcoln/action?msez=500&com=milano&in=via%20solferino&nc=16&_=
(per esempio con curl) riceverete una risposta fatta cosí (ho aggiunto qualche a capo per rendere il tutto piú leggibile):
<code>
0</code>
<x>9.187145</x>
<y>45.4745</y>
<z>0.6</z>
<zcent>0.6</zcent>
<fraz></fraz>
<c>Milano</c>
<com>Milano (MI)/com>
<prov>mi</prov>
<topo>Via Solferino</topo>
<civ>16</civ>
<cdloc>51557</cdloc>
<reg>Lombardia</reg>
<ul></ul> Insomma, un frammento di XML. Frammento perché non ha un elemento radice. L'origine della cosa é ovviamente l'approccio Ajax della pagina di Tuttocittá.
Bene. Questo si presta ad essere utilizzato in modi interessanti. Se fosse XML e non un frammento tutto sarebbe piú semplice.
Supponiamo per esempio di avere un elenco di indirizzi e volerli geocodificare (recuperare le coordinate geografiche) tutti. E magari avere come risultato un file GPX per poter visualizzare i diversi punti in Google Earth. O ancora inviare i punti al proprio GPS.
Supponiamo inoltre che gli indirizzi siano giá in formato XML. Per esempio così:
<results>
<match>
<group id="nome" value="AMANTE CASELLA CENTRO SRL" />
<group id="indirizzo" value="C.SO MATTEOTTI 61 , TORINO 10121 (TO) 011/540641 " />
<group id="tipo" value="C.SO" />
<group id="via" value="MATTEOTTI" />
<group id="civico" value="61" />
<group id="citta" value="TORINO" />
<group id="CAP" value="10121" />
<group id="prov" value="(TO)" />
<group id="tel" value="011/540641" />
</match>
...
</results>
(Questo esempio é stato effettivamente prodotto da uno strumento di prova di espressioni regolari con possibilitá di esportare i risultati in XML). Se l'output di Tuttocittá fosse effettivamente XML potremmo scrivere uno stylesheet XSLT che, facendo leva sulla funcione XPath document() recupera latitudine e longitudine per ogni indirizzo. Cosí non é, ma possiamo scrivere una estensione XSL che ci consenta di trattare opportunamente frammenti XML. Le poche righe di codice C# che seguono servono allo scopo:
using
System;
using System
.IO
;
using System
.Text
;
using System
.Xml
;
using System
.Xml
.XPath
;
using System
.Xml
.Xsl
;
using System
.Net
;
public class DocFrag
{
public XPathNodeIterator
documentFragment
(string url
) {
WebClient
wc
=new WebClient
();
string s
=wc
.DownloadString
(url
);
s
="<root>"+s
+"</root>";
XPathDocument
xd
=new XPathDocument
(new StringReader
(s
));
XPathNavigator
xpn
=xd
.CreateNavigator
();
return xpn
.Select
("/");
}
} (Da compilare con il comando "csc -t:library -debug+ -D:DEBUG docfrag.cs")
Con questa ulteriore arma siamo pronti per scrivere lo stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://www.docfrag.org">
<xsl:output indent='yes'/>
<xsl:template match="*"/>
<xsl:template match="/">
<gpx version="1.1" creator="GPX.XSL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.topografix.com/GPX/1/1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<xsl:for-each select="results/match">
<xsl:variable name='url'>
<xsl:text>http://www.tuttocitta.it/tcoln/action?msez=500&com=</xsl:text>
<xsl:value-of select="group[@id='citta']/@value"/>
<xsl:text>&in=</xsl:text>
<xsl:value-of select="group[@id='tipo']/@value"/>
<xsl:text>%20</xsl:text>
<xsl:value-of select="group[@id='via']/@value"/>
<xsl:text>&nc=</xsl:text>
<xsl:value-of select="group[@id='civico']/@value"/>
<xsl:text>&_=</xsl:text>
</xsl:variable>
<xsl:variable name='doc' select="ext:documentFragment($url)"/>
<xsl:choose>
<xsl:when test='$doc/root/x and $doc/root/y'>
<wpt lon='{$doc/root/x}' lat='{$doc/root/y}'>
<name><xsl:value-of select="group[@id='nome']/@value"/></name>
<desc><xsl:value-of select="group[@id='indirizzo']/@value"/></desc>
</wpt>
</xsl:when>
<xsl:otherwise>
<xsl:message>Non trovato: <xsl:value-of select="group[@id='indirizzo']/@value"/></xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</gpx>
</xsl:template>
</xsl:stylesheet>
Per applicare lo stylesheet utilizzeró l'ottimo nxslt di Oleg Tkachecnko con il comando:
nxslt indirizzi.xml gpx.xsl -af docfrag.dll -ext DocFrag xmlns=http://www.docfrag.org -o p.gpx
...e il gioco é fatto.