Question


I'm developing an Android app in which I created an activity that shows a list of directions taken from Google Directions API.
The url used is something like this: http://maps.googleapis.com/maps/api/directions/xml?origin=Chicago,IL&destination=Los+Angeles,CA&waypoints=Joplin,MO|Oklahoma+City,OK&sensor=false

And the result is something like this:

<DirectionsResponse>
 <status>OK</status>
 <route>
  <summary>I-40 W</summary>
  <leg>
   <step>
    <travel_mode>DRIVING</travel_mode>
    <start_location>
     <lat>41.8507300</lat>
     <lng>-87.6512600</lng>
    </start_location>
    <end_location>
     <lat>41.8525800</lat>
     <lng>-87.6514100</lng>
    </end_location>
    <polyline>
     <points>a~l~Fjk~uOwHJy@P</points>
    </polyline>
    <duration>
     <value>19</value>
     <text>1 min</text>
    </duration>
    <html_instructions>Head <b>north</b> on <b>S Morgan St</b> toward <b>W Cermak Rd</b></html_instructions>
    <distance>
     <value>207</value>
     <text>0.1 mi</text>
    </distance>
   </step>
   ...
   ... additional steps of this leg
  ...
  ... additional legs of this route
   <duration>
    <value>74384</value>
    <text>20 hours 40 mins</text>
   </duration>
   <distance>
    <value>2137146</value>
    <text>1,328 mi</text>
   </distance>
   <start_location>
    <lat>35.4675602</lat>
    <lng>-97.5164276</lng>
   </start_location>
   <end_location>
    <lat>34.0522342</lat>
    <lng>-118.2436849</lng>
   </end_location>
   <start_address>Oklahoma City, OK, USA</start_address>
   <end_address>Los Angeles, CA, USA</end_address>
  <copyrights>Map data ©2010 Google, Sanborn</copyrights>
  <overview_polyline>
   <points>a~l~Fjk~uOnzh@vlbBtc~@tsE`vnApw{A`dw@~w\|tNtqf@l{Yd_Fblh@rxo@b}@xxSfytAblk@xxaBeJxlcBb~t@zbh@jc|Bx}C`rv@rw|@rlhA~dVzeo@vrSnc}Axf]fjz@xfFbw~@dz{A~d{A|zOxbrBbdUvpo@`cFp~xBc`Hk@nurDznmFfwMbwz@bbl@lq~@loPpxq@bw_@v|{CbtY~jGqeMb{iF|n\~mbDzeVh_Wr|Efc\x`Ij{kE}mAb~uF{cNd}xBjp]fulBiwJpgg@|kHntyArpb@bijCk_Kv~eGyqTj_|@`uV`k|DcsNdwxAott@r}q@_gc@nu`CnvHx`k@dse@j|p@zpiAp|gEicy@`omFvaErfo@igQxnlApqGze~AsyRzrjAb__@ftyB}pIlo_BflmA~yQftNboWzoAlzp@mz`@|}_@fda@jakEitAn{fB_a]lexClshBtmqAdmY_hLxiZd~XtaBndgC</points>
  </overview_polyline>
  <optimized_waypoint_index>0</optimized_waypoint_index>
  <optimized_waypoint_index>1</optimized_waypoint_index>
  <bounds>
   <southwest>
    <lat>34.0523600</lat>
    <lng>-118.2435600</lng>
   </southwest>
   <northeast>
    <lat>41.8781100</lat>
    <lng>-87.6297900</lng>
   </northeast>
  </bounds>
 </route>
</DirectionsResponse>

In every item of the list I want to show the information contained in <html_instructions>, <text> child of <distance> and <text> child of <duration>. I was able to obtain the value of <html_instructions> tag, using this parser:

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import android.util.Log;

public class XMLParser {


    public String getXmlFromUrl(String url) {
        String xml = null;

        try {
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            xml = EntityUtils.toString(httpEntity);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // return XML
        return xml;
    }

    public Document getDomElement(String xml){
        Document doc = null;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {

            DocumentBuilder db = dbf.newDocumentBuilder();

            InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));
            doc = db.parse(is); 

            } catch (ParserConfigurationException e) {
                Log.e("Error: ", e.getMessage());
                return null;
            } catch (SAXException e) {
                Log.e("Error: ", e.getMessage());
                return null;
            } catch (IOException e) {
                Log.e("Error: ", e.getMessage());
                return null;
            }

            // return DOM
            return doc;
    }

    public String getValue(Element item, String str) {      
        NodeList n = item.getElementsByTagName(str);        
        return this.getElementValue(n.item(0));
    }

    public final String getElementValue(Node elem) {
         Node child;
         if( elem != null){
             if (elem.hasChildNodes()){
                 for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
                     if( child.getNodeType() == Node.TEXT_NODE  ){
                         return child.getNodeValue();
                     }
                 }
             }
         }
         return "";
    }
}

How can I modify this parser in order to shows also the values of the other two tags?

Was it helpful?

Solution

I was able to fix that by adding another method in XMLParser class:

public String getSecondValue(Element item, String str) {      
    NodeList n = item.getElementsByTagName(str);        
    return this.getElementValue(n.item(1));
}

and here is the usage in the activity:

import java.util.ArrayList;
import java.util.HashMap;

import maps.XMLParser;

import org.apache.commons.lang3.StringEscapeUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;


public class DirectionsActivity extends ListActivity {

    String url = "";
    XMLParser parser;
    String xml = "";
    ArrayList<HashMap<String, String>> menuItems;

    // All static variables
    static final String KEY_STEP = "step"; // parent node
    static final String KEY_HTML_INSTRUCTIONS = "html_instructions";
    static final String KEY_DURATION = "duration";
    static final String KEY_DISTANCE = "distance";
    static final String KEY_TEXT = "text";



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Intent intent = this.getIntent();

        url = intent.getExtras().getString("url");
        System.out.println("---------------" + url);

        menuItems = new ArrayList<HashMap<String, String>>();

        parser = new XMLParser();

        DownloadTask downloadTask = new DownloadTask();

        // Start downloading XML data from Google Directions API
        downloadTask.execute(url);

        // selecting single ListView item
        ListView lv = getListView();        

        // listening to single listitem click
        lv.setOnItemClickListener(new OnItemClickListener() {

           @Override
           public void onItemClick(AdapterView<?> parent, View view,
                   int position, long id) {
               // getting values from selected ListItem
               String instruction = ((TextView) view.findViewById(R.id.instruction)).getText().toString();

               // Starting new intent
               Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
               in.putExtra(KEY_HTML_INSTRUCTIONS, instruction);

               startActivity(in);

           }
       });
    }

    /** A class to download data from Google Directions URL */
    private class DownloadTask extends AsyncTask<String, Void, String>{

        ListAdapter adapter;
        private ProgressDialog pd;

        @Override
        protected void onPreExecute() {
                 pd = new ProgressDialog(DirectionsActivity.this);
                 pd.setTitle("Processing...");
                 pd.setMessage("Calcolo direzione in corso dalla posizione corrente...");
                 pd.setCancelable(false);
                 pd.setIndeterminate(true);
                 pd.show();
        }

        // Downloading data in non-ui thread
        @Override
        protected String doInBackground(String... url) {

            // For storing data from web service
            String data = "";

            try{
                // Fetching the data from web service
                data = parser.getXmlFromUrl(url[0]);
            }catch(Exception e){
                Log.d("Background Task",e.toString());
            }
            return data;
        }

        // Executes in UI thread, after the execution of
        // doInBackground()
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result); 

            Document doc = parser.getDomElement(result); // getting DOM element

            NodeList nl = doc.getElementsByTagName(KEY_STEP);
            // looping through all item nodes <step>
            for (int i = 0; i < nl.getLength(); i++) {
                // creating new HashMap
                HashMap<String, String> map = new HashMap<String, String>();
                Element e = (Element) nl.item(i);
                // adding each child node to HashMap key => value
                String escapedKeyHtmlInstructions = StringEscapeUtils.escapeHtml4(KEY_HTML_INSTRUCTIONS);
                // KEY_HTML_INSTRUCTIONS.replaceAll("\\<.*?>", "");
                map.put(KEY_HTML_INSTRUCTIONS, parser.getValue(e, escapedKeyHtmlInstructions));
                map.put(KEY_DURATION, parser.getValue(e, KEY_TEXT));
                map.put(KEY_DISTANCE, parser.getSecondValue(e, KEY_TEXT));

                // adding HashList to ArrayList
                menuItems.add(map);
            }

            // Adding menuItems to ListView
            adapter = new SimpleAdapter(DirectionsActivity.this, menuItems,R.layout.list_item,
                    new String[] { KEY_HTML_INSTRUCTIONS, KEY_DURATION, KEY_DISTANCE}, new int[] {
                            R.id.instruction, R.id.duration, R.id.distance});

            setListAdapter(adapter);

            pd.dismiss();
        }
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top