Autore Topic: [facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser  (Letto 13137 volte)

Offline Mazinkaiser

  • Nuovo arrivato
  • *
  • Post: 14
  • Debiru Mashin
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Pietrone - 2.0.1 Pulsar
  • Sistema operativo:
    Windows 7 Premium
Livello di difficoltà: facile
Versione SDK utilizzata: 1.6
Link al file compresso del progetto eclipse: file in allegato

Questo Thread è una versione rivista per anddev.it in del tutorial originale in inglese sviluppato da plusminus.
Riferimento a piè pagina e all'interno della documentazione.

Ecco una breve schermata del risultato, per dimostrare i valori ricavati dal seguente XML:

Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<stuff>
   <junk site="http://mazin.altervista.org">
     <test lang="it">Ciau belli!</test>
     <aforisma>XML è meglio</aforisma>
     <tab></tab>
   </junk>
</stuff>

per l'occasione ospitato sul mio (ridicolo) spazio web all'url: http://mazin.altervista.org/sample.xml
Questo è un dettaglio importante, perché, come vedremo, l'XML da analizzare nel tutorial è ricavato da un URL... ma nulla vieta di passarlo anche come file (ma questo è un eventuale approfondimento).

Come si vede dal primo allegato, i campi degli attributi e i valori degli ultimi due tag vengono estratti e passati in una TextView (un po' scarna, ma accontentiamoci).
Nel secondo allegato, invece, è disponibile il project di eclipse, sprovvisto del mio classpath (sarebbe stato inutile visto che ognuno ha il suo), quindi quando lo importate, ricordate di reimpostare le path correttamente. All'interno è presente, nella root, anche l'XML che ho usato.

Sommariamente i concetti chiave sono 3, cioè le rispettive classi (contenute in Parser.java):

  • Parser - prende l'XML, e chiama tutti i metodi.
  • Handler - logica di controllo dei nodi.
  • SingleData - valori passati e salvati.

Mi concentrerò sugli ultimi due per cercare di spiegare al meglio come funziona il codice, mentre il Parser credo sia sufficientemente commentato all'interno del codice.

In sintesi, tramite la classe SAXparser, scorriamo l'intero XML dall'inizio alla fine e, quando troviamo un tag aperto, come ad esempio:

Codice (XML): [Seleziona]
<test>
riferendoci all'xml visto in precedenza, viene chiamato il metodo startElement:

Codice (Java): [Seleziona]
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
...
...
if (localName.equals("test"))  {
                  this.in_test = true;

Dove, con localName, viene passata la stringa all'interno del tag, in questo caso "junk", e in atts i relativi attributi in caso ci siano (ed è questo il caso, con il tag "site").

Uguale discorso si può fare per il metodo di chiusura endElement:

Codice (XML): [Seleziona]
</test>
Codice (Java): [Seleziona]
public void endElement(String namespaceURI, String localName, String qName)
...
...
             if (localName.equals("test")) {
                  this.in_test = false;

La variabile booleana, serve per il metodo character che viene richiamato se all'interno del tag, si trovano dei caratteri. Compito di gestirli è quindi di startElement ed endElement. Che chiamerà un metodo apposta per salvare da qualche parte (consiglio delle liste) i parametri interessati.

Codice (Java): [Seleziona]
 public void characters(char  ch[], int start, int length)  {
             if(this.in_test){
                 xmlparsing.setExtractedString_01(new String(ch, start, length));

Infine, come è stato segnalato, non dimenticate di inserire il permesso per l'accesso ad Internet all'applicazione. Questa riga di codice è da inserire nel file AndroidManifest.xml del vostro progetto.

Codice (XML): [Seleziona]
<uses-permission android:name="android.permission.INTERNET" />

Sorgenti:
Codice (Java): [Seleziona]
package it.anddev;

import java.net.URL;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

/**
 * Classe che fornisce un esempio di parsing xml per il forum anddev.it,
 * basato sul tutorial di plusminus
 * http://www.anddev.org/parsing_xml_from_the_net_-_using_the_saxparser-t353.html
 *
 * @author Mazinkaiser
 */

public class Parser extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView tv = new TextView(this);
        try {
                /* URL passato con l'XML da interrogare*/
                URL url = new URL("http://mazin.altervista.org/sample.xml");
                /* Creiamo un SAXParser dalla classe SAXPArserFactory. */
                SAXParserFactory spf = SAXParserFactory.newInstance();
                SAXParser sp = spf.newSAXParser();
                /* Prendiamo un formato XMLReader dal SAXParser creato */
                XMLReader xr = sp.getXMLReader();
                /* Creiamo un nuovo Handler e passiamoci l'XMLReader*/
                Handler handler = new Handler();
                xr.setContentHandler(handler);
                /* parsing dei xml aprendo lo stream dell'URL. */
                xr.parse(new InputSource(url.openStream()));
                /* Interroghiamo i dati ricavati per estrarne i singoli valori */
                SingleData parsedData = handler.getParsedData();

             /* passiamo il risultato alla TextView per visualizzarli. */
             tv.setText(parsedData.toString());
             
        } catch (Exception e) {
             /* In caso di errore, passiamo l'errore alla TextView. */
             tv.setText("House abbiamo un problema: \n" + e.getMessage());
             Log.e("Error", e.toString());
        }
        /* Montiamo il contenuto della TextView all'interno della View dell'Activity. */
        this.setContentView(tv);
    }
    /**
     * Inner class che gestisce i nodi e salva i parametri
     *
     * @author Mazinkaiser
     *
     */

    public class Handler extends DefaultHandler{

        // ===========================================================
        // Fields
        // ===========================================================
       
        private boolean in_stuff = false;
        private boolean in_junk = false;
        private boolean in_test = false;
        private boolean in_aforisma = false;
        private boolean in_tab = false;
       
        private SingleData xmlparsing = new SingleData();

        // ===========================================================
        // Getter & Setter
        // ===========================================================

        public SingleData getParsedData() {
             return this.xmlparsing;
        }

        // ===========================================================
        // Metodi
        // ===========================================================
        @Override
        public void startDocument() throws SAXException {
             this.xmlparsing = new SingleData();
        }

        @Override
        public void endDocument() throws SAXException {
             /* Niente di utile da inserire */
        }

        /* startElement viene richiamata quando c'è un nuovo tag xml
         * recuperandone i singoli parametri */

        @Override
        public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
             if (localName.equals("stuff")) {
                  this.in_stuff = true;
             }else if (localName.equals("junk")) {
                  this.in_junk = true;
                  String attrValue = atts.getValue("site");
                  xmlparsing.setExtractedStringAttr_01(attrValue);
             }else if (localName.equals("test")) {
                  this.in_test = true;
               // Estrazione dell'attributo
                  String attrValue = atts.getValue("lang");
                  xmlparsing.setExtractedStringAttr_02(attrValue);
             }else if (localName.equals("aforisma")) {
                  this.in_aforisma = true;
             }else if (localName.equals("tab")) {
                 this.in_tab = true;
             }
        }
        /* endElement viene richiamata quando c'è la chiusura di un tag xml */
        public void endElement(String namespaceURI, String localName, String qName)
                  throws SAXException {
             if (localName.equals("stuff")) {
                  this.in_stuff = false;
             }else if (localName.equals("junk")) {
                  this.in_junk = false;
             }else if (localName.equals("test")) {
                  this.in_test = false;
             }else if (localName.equals("aforisma")) {
                 this.in_aforisma = false;
             }else if (localName.equals("tab")) {
                 this.in_tab = false;
             }
        }
       
        /* characters prende i caratteri presenti all'interno di un tag*/
        @Override
       public void characters(char ch[], int start, int length) {
             if(this.in_test){
                 xmlparsing.setExtractedString_01(new String(ch, start, length));
             }else if (this.in_aforisma) {
                 xmlparsing.setExtractedString_02(new String(ch, start, length));
        }
       }
   }
    /**
     * Inner class che salva i parametri usando setter & getter dedicate per ogni nodo.
     *
     * @author Mazinkaiser
     *
     */

    public class SingleData {
        private String extractedItem_01 = null;
        private String extractedItem_02 = null;
        private String extractedItemAttr_01 = null;
        private String extractedItemAttr_02 = null;
       
        public String getExtractedString_01() {
             return extractedItem_01;
        }
        public void setExtractedString_01(String extractedString) {
             this.extractedItem_01 = extractedString;
        }
        public String getExtractedString_02() {
            return extractedItem_02;
        }
        public void setExtractedString_02(String extractedString) {
            this.extractedItem_02 = extractedString;
        }
        public String getExtractedStringAttr_01() {
           return extractedItemAttr_01;
        }
        public void setExtractedStringAttr_01(String extractedString) {
           this.extractedItemAttr_01 = extractedString;
        }
        public String getExtractedStringAttr_02() {
            return extractedItemAttr_02;
         }
         public void setExtractedStringAttr_02(String extractedString) {
            this.extractedItemAttr_02 = extractedString;
         }
       
        public String toString(){
             return "Stringhe estratte:\n\n" +
             this.extractedItemAttr_01+ "\n"+
             this.extractedItemAttr_02+ "\n"+
             this.extractedItem_01+ "\n"+
             this.extractedItem_02+ "\n";
        }
   }
}


Bibliografia:



Spannometricamente, questo è quanto. Forse non è la soluzione migliore, ma io l'ho trovata molto pratica, tantè che per una mia applicazione (tanto per dire) gestivo tramite questi metodi, l'XML disponibile al seguente url (ora recupero i dati da server, cosa un po' diversa):
http://mazin.altervista.org/Configurazione_1.xml

Spero si capisca e torni utile, ovviamente discutiamone :) che conviene a tutti... approposito, non c'è stato verso di usare attributi che contenesserò "xml" come stringa, quelli non riuscivo a passarli, e anche dopo 1 giornata non ne sono venuto a capo -.-
« Ultima modifica: 20 Marzo 2010, 00:36:08 CET da Mazinkaiser »

Offline Mikhael

  • Nuovo arrivato
  • *
  • Post: 24
  • Respect: 0
    • Mostra profilo
    • TuttoAndroid.net
  • Dispositivo Android:
    Nexus One, HTC Dream
  • Play Store ID:
    Costa Mikhael
  • Sistema operativo:
    Windows Vista, Mac Os X
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #1 il: 19 Marzo 2010, 07:17:05 CET »
0
Grazie Mazinkaiser! Era proprio quello ch cercavo, in giornata provo :-)

Offline ChupaChups

  • Utente junior
  • **
  • Post: 78
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
  • Play Store ID:
    fedepupo
  • Sistema operativo:
    Ubuntu/Windows 7
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #2 il: 19 Marzo 2010, 17:33:47 CET »
0
Ciao, ho provato il tuo tutorial, però ho un problemino

Codice: [Seleziona]
Permission denied (maybe missing INTERNET permission)
sai come posso risolvere?
ho copiato "spiccicato" il tuo codice ma nada  :'(

grazie dell'aiuto!

Offline Agafi

  • Utente normale
  • ***
  • Post: 173
  • Respect: +10
    • svetlana-tomasevschi-perini
    • agafist
    • Mostra profilo
  • Dispositivo Android:
    SE Xperia Neo,LG Optimus One,Asus EEE Pad Transformer,HTC Magic Vodafone
  • Play Store ID:
    Agafi
  • Sistema operativo:
    Win7
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #3 il: 19 Marzo 2010, 17:37:40 CET »
0
per correggere il tuo errore devi semplicemente includere questa stringa nel tuo manifest:
Codice: [Seleziona]
<uses-permission android:name="android.permission.INTERNET"></uses-permission>


Offline JD

  • Amministratore
  • Utente storico
  • *****
  • Post: 1600
  • Respect: +232
    • leinardi
    • Mostra profilo
  • Dispositivo Android:
    LG Nexus 5
  • Sistema operativo:
    L'ultima Ubuntu
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #4 il: 19 Marzo 2010, 17:38:35 CET »
0
Prova ad aggiugnere nell'AndroidManifest.xml i permessi per l'accesso ad Internet:
Codice (XML): [Seleziona]
<uses-permission android:name="android.permission.INTERNET" />
Edit:
Ops, sono arrivato tardi :D
È stata trovata una soluzione al tuo problema?
Evidenzia il post più utile premendo . È un ottimo modo per ringraziare chi ti ha aiutato ;).
E se hai aperto tu il thread marcalo come risolto cliccando !

Offline ChupaChups

  • Utente junior
  • **
  • Post: 78
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
  • Play Store ID:
    fedepupo
  • Sistema operativo:
    Ubuntu/Windows 7
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #5 il: 19 Marzo 2010, 17:39:41 CET »
0
perfetto, funziona, grazie mille!

Offline Mazinkaiser

  • Nuovo arrivato
  • *
  • Post: 14
  • Debiru Mashin
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Pietrone - 2.0.1 Pulsar
  • Sistema operativo:
    Windows 7 Premium
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #6 il: 19 Marzo 2010, 22:37:20 CET »
0
mh vero, prossima volta aggiungo anche il dettaglio del manifest :\ (nel file allegato, c'è... ma nella descrizione mi sono dimenticato di specificare che è necessario avere il permesso dal sistema per accedere ad internet).

Offline Mikhael

  • Nuovo arrivato
  • *
  • Post: 24
  • Respect: 0
    • Mostra profilo
    • TuttoAndroid.net
  • Dispositivo Android:
    Nexus One, HTC Dream
  • Play Store ID:
    Costa Mikhael
  • Sistema operativo:
    Windows Vista, Mac Os X
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #7 il: 19 Marzo 2010, 23:50:14 CET »
0
Ho provato anche io e funziona tutto :) una domanda però.. ho modificato a dovere tutto per farlo utilizzare col mio foglio xml però mi prende solo gli ultimi tag del file come è possibile far stampare il parsing totale e non solo gli ultimi dati del file?  :P

Comunque grazie Mazinkaiser per l'aiuto!

Offline JD

  • Amministratore
  • Utente storico
  • *****
  • Post: 1600
  • Respect: +232
    • leinardi
    • Mostra profilo
  • Dispositivo Android:
    LG Nexus 5
  • Sistema operativo:
    L'ultima Ubuntu
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #8 il: 20 Marzo 2010, 00:31:17 CET »
0
mh vero, prossima volta aggiungo anche il dettaglio del manifest :\ (nel file allegato, c'è... ma nella descrizione mi sono dimenticato di specificare che è necessario avere il permesso dal sistema per accedere ad internet).

Puoi sempre cliccare su Modifica e aggiungerlo subito :)
È stata trovata una soluzione al tuo problema?
Evidenzia il post più utile premendo . È un ottimo modo per ringraziare chi ti ha aiutato ;).
E se hai aperto tu il thread marcalo come risolto cliccando !

Offline Mazinkaiser

  • Nuovo arrivato
  • *
  • Post: 14
  • Debiru Mashin
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Pietrone - 2.0.1 Pulsar
  • Sistema operativo:
    Windows 7 Premium
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #9 il: 20 Marzo 2010, 00:39:10 CET »
0
@JD
aggiunto :D

Ho provato anche io e funziona tutto :) una domanda però.. ho modificato a dovere tutto per farlo utilizzare col mio foglio xml però mi prende solo gli ultimi tag del file come è possibile far stampare il parsing totale e non solo gli ultimi dati del file?  :P

Comunque grazie Mazinkaiser per l'aiuto!

Beh è curioso, allora confermo che "sembra" schizzinoso, perchè per esempio, non sono riuscito a prendere i dati da attributi con all'interno "xml", quindi potrebbe essere qualche altra combinazioni di caratteri che da noia... ma sarebbe davvero una bella sfiga. Da quello che accenni sembra più un errore da qualche parte durante il codice, perchè se è tutto corretto dovrebbe funzionare. Altrimenti se vuoi linka il codice e xml e ci ragioniamo su.

Figurati :)

Offline Mikhael

  • Nuovo arrivato
  • *
  • Post: 24
  • Respect: 0
    • Mostra profilo
    • TuttoAndroid.net
  • Dispositivo Android:
    Nexus One, HTC Dream
  • Play Store ID:
    Costa Mikhael
  • Sistema operativo:
    Windows Vista, Mac Os X
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #10 il: 20 Marzo 2010, 00:47:45 CET »
0
Si ma penso che capiti anche se tu provi a duplicare i tag nel tuo xml... i dati che prende saranno sempre gli ultimi oppure col tuo li prende tutti uno dopo l'altro?
Quello che avevo pensato (io come linguaggio di script sò solo php) di provare a mettere tutto in un array e parsarlo a sua volta o boh.. il problema è che secondo me ogni volta che trova i tag sostituisce quelli che aveva trovato in precedenza arrivando all'ultimo che esce e quindi dà gli ultimi risultati... non c'è un modo che invece che andarli a sostituire li aggiunga?

es.
public {
dati = dati + dati
}

print dati

(scusami la sinteticità xD)

Offline andy0087

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
    • TuttoPhone.com
  • Dispositivo Android:
    HTC Dream
  • Sistema operativo:
    Windows 7
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #11 il: 20 Marzo 2010, 03:50:28 CET »
0
Ho provato anche io e funziona tutto :) una domanda però.. ho modificato a dovere tutto per farlo utilizzare col mio foglio xml però mi prende solo gli ultimi tag del file come è possibile far stampare il parsing totale e non solo gli ultimi dati del file?  :P

Comunque grazie Mazinkaiser per l'aiuto!
Stesso problema di Mikhael, ho provato a utilizzarlo su un feed RSS ma purtroppo mi stampa solo gli ultimi dati del file e non tutti.
.. il problema è che secondo me ogni volta che trova i tag sostituisce quelli che aveva trovato in precedenza arrivando all'ultimo che esce e quindi dà gli ultimi risultati...
Anch'io penso che sia questo il problema!

Offline Mikhael

  • Nuovo arrivato
  • *
  • Post: 24
  • Respect: 0
    • Mostra profilo
    • TuttoAndroid.net
  • Dispositivo Android:
    Nexus One, HTC Dream
  • Play Store ID:
    Costa Mikhael
  • Sistema operativo:
    Windows Vista, Mac Os X
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #12 il: 21 Marzo 2010, 13:29:22 CET »
0
Nessuno riesce a darci un'altra manina?  :P

Offline Mazinkaiser

  • Nuovo arrivato
  • *
  • Post: 14
  • Debiru Mashin
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Pietrone - 2.0.1 Pulsar
  • Sistema operativo:
    Windows 7 Premium
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #13 il: 25 Marzo 2010, 17:46:00 CET »
0
Questo week-end guardo se capisco dove falla =.=,

Offline Mikhael

  • Nuovo arrivato
  • *
  • Post: 24
  • Respect: 0
    • Mostra profilo
    • TuttoAndroid.net
  • Dispositivo Android:
    Nexus One, HTC Dream
  • Play Store ID:
    Costa Mikhael
  • Sistema operativo:
    Windows Vista, Mac Os X
Re:[facile] Ottenere dati da tag XML noti da URL, metodo tramite SAXparser
« Risposta #14 il: 26 Marzo 2010, 22:44:00 CET »
0
Questo week-end guardo se capisco dove falla =.=,
Ok, io intanto sto testando per conto mio ma ancora non ne sono giunto a capo