Parsing XML from the Net - Using the SAXParser

Basic Tutorials concerning: GUI, Views, Activites, XML, Layouts, Intents, ...

Postby padde » Wed Oct 14, 2009 12:04 pm

Hmm.. the first thing that comes to my mind is this:

Code: Select all
1. build a handler for the thread you want to work with the data
2. count the times the sax parsers reads the desired start tag and fill an array with the data you read
3. in the startelement method when desired tag is read check if the count fits your needs.
    If so send a message to the handler from 1 with the data array you collected. After that reset counter
    and clear the array.


Well.. i think you get the idea..
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Top

Postby steven_d » Wed Oct 14, 2009 12:47 pm

Thanks for the fast answer.
but this is only possible, if i have the "SaxParser"-class in the same java file, isn't it? Because i can't use the handler from the thread from another java file!?
So must i choose between this two options?:
1) all in one java file, but with the possibility to get information earlier ==> my source code gets longer and longer
2) have several java files but i can't do, what i want...

Thanks,
Stefan
steven_d
Junior Developer
Junior Developer
 
Posts: 12
Joined: Mon Jul 20, 2009 1:15 pm
Location: Germany

Postby padde » Wed Oct 14, 2009 1:12 pm

Well.. no.. just pass the handler object over to the class that extends the DefaultHandler.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. class MyHandler extends DefaultHandler {
  3.  
  4.     private Handler mhandler;
  5.  
  6.     ...
  7.  
  8.  
  9.  
  10.     public MyHandler(Handler h) {
  11.  
  12.         super();
  13.  
  14.         this.mhandler = h;
  15.  
  16.     }
  17.  
  18.  
  19.  
  20.     public void startDocument() throws SAXException { ... }
  21.  
  22.     public void endDocument() throws SAXException { ... }
  23.  
  24.     public void startElement(String n, String l, String q, Attributes a) { ... }
  25.  
  26.     public void endDocument(String n, String l, String q, Attributes a) { ... }
  27.  
  28.     public void characters(char[] c, int s, int l) { ... }
  29.  
  30. }
  31.  
  32.  
Parsed in 0.033 seconds, using GeSHi 1.0.8.4


like that.. and then use mHandler to send messages to.
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Re: getting null when using ArrayList for tags

Postby android2 » Sat Oct 17, 2009 11:54 am

Visualiza places I have to present in a kml in a list help me thanks

Ant1 wrote:Hello again PlusMinus first let me say thanks for all the help with my two questions and the advice given has helped but now I'm stuck again :cry:

I've used the ArrayList to store the 22 tags I need and I try to access them in the characters method but when I run the emulator all I get is a message saying null and I don't even get the double values here is my code again

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. import java.util.ArrayList;
  3.  
  4. import org.xml.sax.Attributes;
  5. import org.xml.sax.SAXException;
  6. import org.xml.sax.helpers.DefaultHandler;
  7.  
  8. public class ExampleHandler extends DefaultHandler {
  9.        
  10.        
  11.         //test tags see if we have to parse the whole document
  12.         //or only the part we want ???
  13.        
  14.         private boolean in_curr_tag = false;
  15.         private boolean in_obs_tag = false;
  16.        
  17.         //ArrayList to hold all the time we hit the closing tags </in_curr_tag>
  18.         private ArrayList<ParsedExampleDataSet> list = new ArrayList<ParsedExampleDataSet>(22);
  19.        
  20.         private ParsedExampleDataSet peds = new ParsedExampleDataSet();
  21.        
  22.         public ParsedExampleDataSet getParsedData(){
  23.                 return this.peds;
  24.         }
  25.        
  26.         @Override
  27.         public void startDocument() throws SAXException {
  28.                 this.peds = new ParsedExampleDataSet();
  29.         }
  30.        
  31.         @Override
  32.         public void endDocument() throws SAXException {
  33.                 //nothing to do here
  34.         }
  35.        
  36.         /*
  37.          * Gets be called on opening tags like
  38.          * <tag>
  39.          * Can provide attribute(s), when xml was like:
  40.          * <tag attribute="attributeValue">*/
  41.          @Override
  42.          public void startElement(String namespaceURI, String localName,
  43.                                                                 String qName, Attributes atts)throws SAXException{
  44.                  
  45.                  if(localName.equals("frbny:CURR")){
  46.                          this.in_curr_tag = true;
  47.                  }else if(localName.equals("frbny:OBS_VALUE")){
  48.                          this.in_obs_tag = true;
  49.                  }
  50.          }
  51.          
  52.          //Called on closing tags like </tag>
  53.          @Override
  54.          public void endElement(String namespaceURI, String localName, String qName) throws SAXException{
  55.                  
  56.                  
  57.                  if(localName.equals("frbny:CURR")){
  58.                         //add all 22 tags to the ArrayList
  59.                          for(int i = 1; i < list.size(); i++){
  60.                                  list.add(i, peds);
  61.                          }
  62.                          //testing purposes only
  63.                          //peds.setExtractedInt(list.size());
  64.                          this.in_curr_tag = false;
  65.                  }else if(localName.equals("frbny:OBS_VALUE")){
  66.                          this.in_obs_tag = false;
  67.                  }
  68.                  
  69.                
  70.          }
  71.          
  72.          /** Gets be called on the following structure:
  73.       * <tag>characters</tag> */
  74.      @Override
  75.     public void characters(char ch[], int start, int length) {
  76.          
  77.          if(this.in_curr_tag){ 
  78.                  peds = list.get(0);
  79.                  peds.setExtractedString(new String(ch, start, length));
  80.          }
  81.          if(this.in_obs_tag){
  82.                  peds.setExtractedDouble(Double.parseDouble(new String(ch, start, length)));
  83.          }
  84.          
  85.          
  86.     }
  87. }
  88.  
  89.  
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


I'm not sure if I need another for loop to access the ParsedExampleDataSets or not but I don't think so. My question is why am I not able to access the individual tags of the file, I have overloaded the setExtractedString method in the ParsedExampleDataSet class to accept an int along with the String so I can run through the list but again I am not sure if this is necessary. I have gone through google's webpage for the ArrayList class I don't think I missed anything but many eyes are better then one :wink: Thanks for any help in advance again

Anthony
android2
Developer
Developer
 
Posts: 48
Joined: Sun Oct 04, 2009 8:34 pm

kml in listview

Postby android2 » Sat Oct 17, 2009 11:59 am

I must see these places in a kml in a list help me thanks
padde wrote:Well.. no.. just pass the handler object over to the class that extends the DefaultHandler.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. class MyHandler extends DefaultHandler {
  2.     private Handler mhandler;
  3.     ...
  4.  
  5.     public MyHandler(Handler h) {
  6.         super();
  7.         this.mhandler = h;
  8.     }
  9.  
  10.     public void startDocument() throws SAXException { ... }
  11.     public void endDocument() throws SAXException { ... }
  12.     public void startElement(String n, String l, String q, Attributes a) { ... }
  13.     public void endDocument(String n, String l, String q, Attributes a) { ... }
  14.     public void characters(char[] c, int s, int l) { ... }
  15. }
  16.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


like that.. and then use mHandler to send messages to.
android2
Developer
Developer
 
Posts: 48
Joined: Sun Oct 04, 2009 8:34 pm

Unknow error

Postby firewall7845 » Wed Oct 21, 2009 9:06 am

Hi all,
I'm newbie and i'm researching on XML Parser

I have complied the PARSING XML Tutorial at page 1 ( author: Plusminus) but i get output " Error: Unknow error"
and when i run debug, i see that at the onCreate method

Debugger stop at line :

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. xr.parse(new InputSource(url.openStream()))
Parsed in 0.034 seconds, using GeSHi 1.0.8.4


and after that it jump to Exception:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.      } catch (Exception e) {
  2.                /* Display any Error to the GUI. */
  3.                tv.setText("Error: " + e.getMessage());
  4.                Log.e(MY_DEBUG_TAG, "WeatherQueryError", e);
  5.           }
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


Something wrong with line: xr.parse(new InputSource(url.openStream()))

Any ideas? thank in advance :)
firewall7845
Once Poster
Once Poster
 
Posts: 1
Joined: Wed Oct 21, 2009 8:53 am

Top

Internet Connection Error

Postby booyakah » Sat Oct 24, 2009 5:16 pm

When running the source code I get error saying "Error: Permission Denied (maybe missing INTERNET permission)".

When I am trying to turn off WiFI in the emulator it says "unable to start wifi". I have tried googling but have only found solutions concerning emulators behind proxys. My computer that is running the emulator is connected with wifi through a router.

Does anyone know how to fix this error?

edit: I also cannot browse with the browser in the emulator if that wasn't obvious

*edit2: SOLVED IT!

Had to add

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. <uses-permission android:name="android.permission.INTERNET" />
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


to the AndroidManifest.xml
booyakah
Freshman
Freshman
 
Posts: 2
Joined: Fri Oct 23, 2009 8:08 pm

Postby SeraphimSerapis » Mon Oct 26, 2009 1:41 pm

i'm trying to parse a XML from the web, but my problem is that the encoding is Windows-1252 with special characters ö,ü,ä and €.
when i'm trying to parse this xml with sax i get an error: "not well-formed (invalid token)".

is there a solution for this problem? i can't change the XML because it is a public file from my university.

i thought about reading out the file with java, change the characters and save it to the sdcard, but i think this will slow down the app.



regards,
tim
SeraphimSerapis
Junior Developer
Junior Developer
 
Posts: 14
Joined: Wed Mar 11, 2009 10:57 pm

Postby padde » Mon Oct 26, 2009 3:36 pm

Could you provide an example XML file to play with?!
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Postby SeraphimSerapis » Mon Oct 26, 2009 4:10 pm

SeraphimSerapis
Junior Developer
Junior Developer
 
Posts: 14
Joined: Wed Mar 11, 2009 10:57 pm

Postby padde » Mon Oct 26, 2009 9:30 pm

Okay.. i found a way.. but its realy not that nice.
The problem is the encoding. If you change it to UTF-8 all is fine but
i guess you have no influence on the xml creation so i created a method
that changes encoding on the fly.
Example follows...


XmlParser.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.padde.xmlparser;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.widget.TextView;
  6.  
  7. public class XmlParser extends Activity {
  8.     public static String lol = ""; //because i'am lazy <img src="http://www.anddev.org/images/smilies/smile.png" alt=":)" title="Smile" />
  9.    
  10.     public void onCreate(Bundle savedInstanceState) {
  11.         super.onCreate(savedInstanceState);
  12.         setContentView(R.layout.main);
  13.        
  14.         //i downloaded the XML you provided and imported it to the res/raw folder
  15.         XmlReader.read(getResources().openRawResource(R.raw.mensa));
  16.        
  17.         TextView tv = (TextView) findViewById(R.id.text);
  18.         tv.setText(lol);
  19.     }
  20. }
  21.  
Parsed in 0.038 seconds, using GeSHi 1.0.8.4


XmlReader.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.padde.xmlparser;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.InputStreamReader;
  7. import java.io.StringReader;
  8. import java.io.UnsupportedEncodingException;
  9.  
  10. import javax.xml.parsers.ParserConfigurationException;
  11. import javax.xml.parsers.SAXParser;
  12. import javax.xml.parsers.SAXParserFactory;
  13.  
  14. import org.xml.sax.InputSource;
  15. import org.xml.sax.SAXException;
  16. import org.xml.sax.XMLReader;
  17.  
  18. public class XmlReader {
  19.     public static void read(InputStream in) {
  20.        
  21.         SAXParserFactory spf = SAXParserFactory.newInstance();
  22.         SAXParser sp;
  23.         try {
  24.             sp = spf.newSAXParser();
  25.             XMLReader xr = sp.getXMLReader();
  26.             XmlContentHandler ach = new XmlContentHandler();
  27.             xr.setContentHandler(ach);
  28.             xr.parse(changeEncoding(in,"windows-1252","utf-8"));
  29.         } catch (ParserConfigurationException e) {
  30.         } catch (SAXException e) {
  31.         } catch (IOException e) {}
  32.     }
  33.    
  34.     private static InputSource changeEncoding(InputStream in, String from, String to) {
  35.         String f = from.toLowerCase();
  36.         String t = to.toLowerCase();
  37.         try {
  38.             BufferedReader br = new BufferedReader(new InputStreamReader(in,f));
  39.             StringBuilder sb = new StringBuilder();
  40.             String l = br.readLine().toLowerCase().replace(f, t);
  41.             sb.append(l+"n");
  42.             while ((l = br.readLine()) != null) sb.append(l+"n");
  43.             br.close();
  44.             return new InputSource(new StringReader(sb.toString()));
  45.         } catch (UnsupportedEncodingException e) {
  46.         } catch (IOException e) {}
  47.         return null;
  48.     }
  49. }
  50.  
Parsed in 0.045 seconds, using GeSHi 1.0.8.4


XmlContentHandler.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.padde.xmlparser;
  2.  
  3. import org.xml.sax.Attributes;
  4. import org.xml.sax.SAXException;
  5. import org.xml.sax.helpers.DefaultHandler;
  6.  
  7. public class XmlContentHandler extends DefaultHandler {
  8.     private enum Tags {
  9.         tag, menue, menu, speisentyp, text, beilage, preis, ausgabe, datum, wochentag,
  10.         stand, bis, von, plan, kw, planbezeichnung, filiale
  11.     }
  12.    
  13.     private boolean in_menuTag = false;
  14.  
  15.     public void startDocument() throws SAXException { }
  16.     public void endDocument() throws SAXException { }
  17.  
  18.     public void startElement(String n, String l, String q, Attributes a) {
  19.          switch(Tags.valueOf(l)) {
  20.              case menu:
  21.                  in_menuTag = true;
  22.                  break;
  23.          }
  24.     }
  25.      
  26.     public void endElement(String n, String l, String q) {
  27.         switch(Tags.valueOf(l)) {
  28.             case menu:
  29.                 in_menuTag = false;
  30.                 break;
  31.         }
  32.     }
  33.      
  34.     public void characters(char ch[], int start, int length) {
  35.         if(in_menuTag) {
  36.             XmlParser.lol += new String(ch,start,length) + "n";
  37.         }
  38.     }
  39. }
  40.  
Parsed in 0.041 seconds, using GeSHi 1.0.8.4


main.xml
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.    android:orientation="vertical"
  4.    android:layout_width="fill_parent"
  5.    android:layout_height="fill_parent">
  6.  
  7.     <TextView  
  8.        android:id="@+id/text"
  9.        android:layout_width="fill_parent"
  10.        android:layout_height="wrap_content"
  11.    />
  12. </LinearLayout>
  13.  
Parsed in 0.002 seconds, using GeSHi 1.0.8.4


Note:
The XmlContentHandler just parse menu titles because they contain already a special character (ü)
and because i'm lazy :lol:
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Postby SeraphimSerapis » Tue Oct 27, 2009 12:16 am

I really appreciate your work, padde.
Thank you very much for helping me.

One question left: You do work with a downloaded file in the raw folder. Is it possible for me do download the file while using the App and save it to the raw folder?

Regards, Tim
SeraphimSerapis
Junior Developer
Junior Developer
 
Posts: 14
Joined: Wed Mar 11, 2009 10:57 pm

Postby padde » Tue Oct 27, 2009 1:52 am

Well i thought you already have the code to download the xml.
Here is the changed XmlParser class to download the xml from web instead of loading it from res/raw.

XmlParser.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.padde.xmlparser;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5.  
  6. import org.apache.http.client.ClientProtocolException;
  7. import org.apache.http.client.methods.HttpPost;
  8. import org.apache.http.impl.client.DefaultHttpClient;
  9.  
  10. import android.app.Activity;
  11. import android.os.AsyncTask;
  12. import android.os.Bundle;
  13. import android.widget.TextView;
  14.  
  15. public class XmlParser extends Activity {
  16.     public static String lol = ""; //because i'am lazy <img src="http://www.anddev.org/images/smilies/smile.png" alt=":)" title="Smile" />
  17.     private TextView tv;
  18.    
  19.     public void onCreate(Bundle savedInstanceState) {
  20.         super.onCreate(savedInstanceState);
  21.         setContentView(R.layout.main);
  22.        
  23.         tv = (TextView) findViewById(R.id.text);
  24.  
  25.         new parseXMLfromWeb().execute("http://www.studentenwerk-pb.de/fileadmin/xml/mensa.xml");
  26.     }
  27.    
  28.     private class parseXMLfromWeb extends AsyncTask<String, Void, InputStream> {
  29.         protected InputStream doInBackground(String... url) {
  30.             try {
  31.                 return new DefaultHttpClient().execute(new HttpPost(url[0])).getEntity().getContent();
  32.             } catch (IllegalStateException e) {
  33.             } catch (ClientProtocolException e) {
  34.             } catch (IOException e) {}
  35.             return null;
  36.         }
  37.        
  38.         protected void onPostExecute(InputStream result) {
  39.             XmlReader.read(result);
  40.             tv.setText(lol);
  41.         }
  42.     }
  43. }
  44.  
Parsed in 0.042 seconds, using GeSHi 1.0.8.4
padde
Master Developer
Master Developer
 
Posts: 443
Joined: Wed Apr 08, 2009 4:52 pm

Postby SeraphimSerapis » Tue Oct 27, 2009 1:30 pm

Thank you very much padde.
Great work you did there.


Hopefully I can help here somebody soon ;)


Regards Tim
SeraphimSerapis
Junior Developer
Junior Developer
 
Posts: 14
Joined: Wed Mar 11, 2009 10:57 pm

Not showing the perfect output

Postby base2coder » Sun Nov 01, 2009 8:37 am

Hello Plusminus...thanks for the nice piece of code. I have run the code. but it is not showing the perfect output as you shown...it is showing....

ExtractedString=
ExtractedInt=1337

there is nothing showing after the ExtractedString....can you tell me what is the error or how can i do to see the string you told "anddev.org rulez =)"

i have run the exact code as you given..thanks in advace for your co=operation....
base2coder
Junior Developer
Junior Developer
 
Posts: 14
Joined: Sun Jul 12, 2009 8:54 pm

Top
PreviousNext

Return to Novice Tutorials

Who is online

Users browsing this forum: No registered users and 7 guests