Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1908, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Disabilita cookie ShinyStat

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Xamarin Certified Mobile Developer

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Parsing di HTML con LINQ to XML in Windows 8

Premessa

Probabilmente qualcuno di voi ha scaricato Forze dell'Ordine, una mia app per Windows 8 che aggrega le ultime notizie sulle attività dei Corpi di Polizia dello Stato.

La primissima versione di quest'app, lo ammetto, è stata fatta un po' frettolosamente quindi per ogni notizia viene mostrato anche automaticamente l'articolo completo aprendo la pagina Web del sito in un controllo WebView.

Un po' per consapevolezza, un po' per i feedback, non appena ho avuto un po' di tempo ho deciso di mettere mano al codice, facendo sì che l'app mostri solo il contenuto dell'anteprima dell'articolo e, solo a richiesta dell'utente, visualizzi l'articolo originale nella sua pagina Web (certificata e già in Store).

Problema: il feed di una delle Forze dell'Ordine non ha l'anteprima del contenuto.

Soluzione: scarico l'articolo e recupero l'HTML corrispondente al contenuto, cosa che non avevo mai fatto.

Ragionamenti

Notoriamente non sono mai stato un esperto di HTML e tanto meno del suo parsing. Però posso dire di essere piuttosto esperto di LINQ. Quindi mi sono detto: HTML è markup, XML è markup, XHTML è markup.. quindi posso usare LINQ to XML e gli XML Literals di VB, facendo leggere il contenuto di una pagina HTML alla classe XElement di LINQ.

Come fare

Per cominciare ho letto questo vecchio post di Beth Massi, risalente al 2008. Faceva proprio al caso mio, sia perché conosco qual è il tag HTML da interrogare, sia perché mostra l'uso degli XML Literals.

Ovviamente il presupposto è che il documento HTML da analizzare sia di tipo XHTML "well formed", ossia strutturato secondo regola. Diversamente, conviene ricorrere ad altri tool.

Il punto di vista di Windows 8

Nel riadattare il codice di Beth a Windows 8 (leggetelo altrimenti vi perdete), c'è un particolare: il metodo GetHtmlPage fa un'invocazione al metodo WebRequest.GetResponse, che in WinRT non è disponibile. In questa tecnologia, infatti, abbiamo GetResponseAsync e questo ha senso. Bisogna quindi riscrivere quel codice trasformandolo in asincrono, come segue:

    Async Function GetHtmlPageAsync(ByVal strURL As StringAs Task(Of String)
        Try
 
            Dim strResult As String
            Dim objResponse As WebResponse
            Dim objRequest As WebRequest = HttpWebRequest.Create(strURL)
            objRequest.UseDefaultCredentials = True
 
            objResponse = Await objRequest.GetResponseAsync
            Using sr As New StreamReader(objResponse.GetResponseStream())
                strResult = Await sr.ReadToEndAsync
            End Using
 
            'Replace HTML entity references so that we can load into XElement
            strResult = strResult.Replace(" """)
            strResult = strResult.Replace("&""&")
            Return strResult
 
        Catch ex As Exception
            Return ""
        End Try
    End Function

 A questo punto non mi resta che leggere la pagina HTML in modalità asincrona e analizzarne il contenuto:

                    Dim page = Await GetHtmlPageAsync("http://www.sito.com/pagina.html")
                    html = XElement.Parse(page)
 
                    query = From item In html...<div>
                            Select item.<p>.Value

Ovviamente la query va personalizzata secondo le vostre esigenze e il codice presuppone la seguente direttiva Imports, altrimenti non otterrete nulla... :

Imports <xmlns="http://www.w3.org/1999/xhtml">

Ovviamente questa non è la soluzione per tutti i problemi, però è un modo abbastanza rapido soprattutto se si conosce a priori la struttura del vostro documento XHTML.

Alessandro

Print | posted on giovedì 21 marzo 2013 19:48 | Filed Under [ UWP e Windows Store Apps ]

Powered by:
Powered By Subtext Powered By ASP.NET