Android: Simple XML SAX Parser – Displays Same Data Over and Over

All we need is a simple explanation of the problem, which is provided below.

I’ve created an XML parser which populates a listView with data obtained from an XML file. The problem is for some reason the listView shows the same data over and over instead of unique data for each listView item.

I’m not sure exactly what is causing this issue – any insight is greatly appreciated.

Screenshot:

enter image description here

XML Data:

<response>
<cmd>getVideos</cmd>
<success>1</success>
<NumberOfVideos>4</NumberOfVideos>
<Videos>
<Video>
<VideoName>sample_iPod</VideoName>
<VideoDesc/>
<VideoUrl>

</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_mpeg4</VideoName>
<VideoDesc/>
<VideoUrl>

</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_sorenson</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/2a8e64b24997.mov
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_iTunes</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/6c7f65254aad.mov
</VideoUrl>
<VideoTags/>
</Video>
</Videos>
</response>

Example/Tutorial:

http://theopentutorials.com/tutorials/android/xml/android-simple-xml-sax-parser-tutorial/

SAXXMLHandler.java

     public class SAXXMLHandler extends DefaultHandler {
    private List<Cmd> videos;
    private String tempVal;
    // to maintain context
    private Cmd cmd;

    public SAXXMLHandler() {
        videos = new ArrayList<Cmd>();
    }

    public List<Cmd> getResponse() {
        return videos;
    }

    // Event Handlers
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        // reset
        tempVal = "";
        if (qName.equalsIgnoreCase("Video")) {
            // create a new instance of cmd
            cmd = new Cmd();

        }
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        tempVal = new String(ch, start, length);
    }

    public void endElement(String uri, String localName, String qName)
            throws SAXException {
  if (qName.equalsIgnoreCase("videos")) {
            // add it to the list
        } else if (qName.equalsIgnoreCase("success")) {
            cmd.setSuccess(tempVal);
        } else if (qName.equalsIgnoreCase("numberofvideos")) {
            cmd.setNumberOfVideos(tempVal);
        } else if (qName.equalsIgnoreCase("videos")) {
            cmd.setVideos(videos);
        } else if (qName.equalsIgnoreCase("video")) {
            cmd.setVideo(tempVal);
        } else if (qName.equalsIgnoreCase("videoname")) {
            cmd.setVideoName(tempVal);
        } else if (qName.equalsIgnoreCase("videourl")) {
            cmd.setVideoURL(tempVal);
            videos.add(cmd); //You only need store an instance of your Cmd 
        }
      }
    }

CustomListViewAdapter.java

public class CustomListViewAdapter extends ArrayAdapter<Cmd> {
    Activity context;
    List<Cmd> videos;

    public CustomListViewAdapter(Activity context, List<Cmd> videos) {
        super(context, R.layout.list_item2, videos);
        this.context = context;
        this.videos = videos;
    }

    /*private view holder class*/
    private class ViewHolder {
        ImageView imageView;
        TextView txtSuccess;
        TextView txtCmd;
        TextView txtPrice;
    }

    public Cmd getItem(int position) {
        return videos.get(position);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        LayoutInflater inflater = context.getLayoutInflater();

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.list_item2, null);
            holder = new ViewHolder();
            holder.txtSuccess = (TextView) convertView.findViewById(R.id.success);
            holder.txtCmd = (TextView) convertView.findViewById(R.id.cmd);
            holder.txtPrice = (TextView) convertView.findViewById(R.id.price);
            holder.imageView = (ImageView) convertView.findViewById(R.id.thumbnail);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Cmd cmd = (Cmd) getItem(position);


        holder.txtSuccess.setText(cmd.getSuccess());
            holder.txtCmd.setText(cmd.getCmd());
         //   holder.imageView.setImageBitmap(cmd.getImageBitmap());
            holder.txtPrice.setText(cmd.getVideoName() + "");

        return convertView;
    }
}

SAXParserAsyncTaskActivity.java

public class SAXParserAsyncTaskActivity extends Activity implements
OnClickListener, OnItemClickListener {
    Button button;
    ListView listView;
    List<Cmd> videos = new ArrayList<Cmd>();

    CustomListViewAdapter listViewAdapter;

    static final String URL = "http://mobile.example.com/api/xmlrpc.php?cmd=getVideos&username=fake&password=credential";
    public static final String LIBRARY = "Library";

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.parser_main);

        findViewsById();
        button.setOnClickListener(this);
        listView.setOnItemClickListener(this);

        GetXMLTask task = new GetXMLTask(this);
        task.execute(new String[] { URL });
    }

    private void findViewsById() {
        button = (Button) findViewById(R.id.button);
        listView = (ListView) findViewById(R.id.cmdList);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
    }

    @Override
    public void onClick(View view) {
        // GetXMLTask task = new GetXMLTask(this);
        // task.execute(new String[] { URL });
    }

    // private inner class extending AsyncTask
    private class GetXMLTask extends AsyncTask<String, Void, List<Cmd>> {
        private Activity context;

        public GetXMLTask(Activity context) {
            this.context = context;
        }


        protected void onPostExecute(List<Cmd> videos) {
            listViewAdapter = new CustomListViewAdapter(context, videos);
            listView.setAdapter(listViewAdapter);
        }

        /*
         * uses HttpURLConnection to make Http request from Android to download
         * the XML file
         */
        private String getXmlFromUrl(String urlString) {
            StringBuffer output = new StringBuffer("");
            try {
                InputStream stream = null;
                URL url = new URL(urlString);
                URLConnection connection = url.openConnection();

                HttpURLConnection httpConnection = (HttpURLConnection) connection;
                httpConnection.setRequestMethod("GET");
                httpConnection.connect();

                if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    stream = httpConnection.getInputStream();

                    BufferedReader buffer = new BufferedReader(
                            new InputStreamReader(stream));
                    String s = "";
                    while ((s = buffer.readLine()) != null)
                        output.append(s);
                }

            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return output.toString();
        }

        @Override
        protected List<Cmd> doInBackground(String... urls) {
            List<Cmd> videos = null;
            String xml = null;
            for (String url : urls) {
                xml = getXmlFromUrl(url);

                InputStream stream = new ByteArrayInputStream(xml.getBytes());
                videos = SAXXMLParser.parse(stream);

if ( videos == null) {
                Toast.makeText(getApplicationContext(), "Videos is null!)",
                           Toast.LENGTH_LONG).show();

            }
                for (Cmd cmd : videos) {
                    String videoName = cmd.getVideoName();
                    // String getVideos = cmd.getVideos();
//                    String getVideo = cmd.getVideo();
//                    String getVideoURL = cmd.getVideoURL();
//                    String getNumberOfVideos = cmd.getNumberOfVideos();
//
//                    Bitmap bitmap = null;
//                    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
//                    bmOptions.inSampleSize = 1;
//
//                    try {
//                        bitmap = BitmapFactory.decodeStream(
//                                new URL(videoName).openStream(), null,
//                                bmOptions);
//                    } catch (MalformedURLException e) {
//                        e.printStackTrace();
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    }
                }
            }
            // stream.close();
            return videos;
        }
    }
}

Let’s Solve it:

This is a common error many developers questioned us about it. So we write the explanation above. You just have to apply the suggested solution to your code and it will do for you. If you still getting this error after applying this code then comment below we will get back to you with the new method.

Solution 1

You are creating only one instance of Cmd() that is overriding itself, because you have only one <cmd> element.

Change:

 if (qName.equalsIgnoreCase("cmd")) {
            // create a new instance of cmd
            cmd = new Cmd();

        }

to:

 if (qName.equalsIgnoreCase("Video")) {
            // create a new instance of cmd
            cmd = new Cmd();

        }

You need to create an instance of Cmd() when your parser read every <Video> element.

and change your endElement(String uri, String localName, String qName) method to:

  public void endElement(String uri, String localName, String qName)
            throws SAXException {
  if (qName.equalsIgnoreCase("videos")) {
            // add it to the list
        /*} else if (qName.equalsIgnoreCase("success")) {
            cmd.setSuccess(tempVal);
        } else if (qName.equalsIgnoreCase("numberofvideos")) {
            cmd.setNumberOfVideos(tempVal);
        } else if (qName.equalsIgnoreCase("videos")) {
            cmd.setVideos(videos);
        } else if (qName.equalsIgnoreCase("video")) {
            cmd.setVideo(tempVal);*/
        } else if (qName.equalsIgnoreCase("videoname")) {
            cmd.setVideoName(tempVal);
        } else if (qName.equalsIgnoreCase("videourl")) {
            cmd.setVideoURL(tempVal);
            videos.add(cmd); //You only need store an instance of your Cmd 
        }
      }

Note: You are free to use these solutions for your personal use. We recommend you apply the first solution to your code because it was tested in our system before posting it on this page.

We are always trying to help the developer community, So we made their work easy. Basically, we collected these data from stackoverflow.com, As it is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0.

Leave a Comment