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

冷暖自知 提交于 2020-01-05 04:19:05

问题


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:

XML Data:

<response>
<cmd>getVideos</cmd>
<success>1</success>
<NumberOfVideos>4</NumberOfVideos>
<Videos>
<Video>
<VideoName>sample_iPod</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/06087297988b.m4v
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_mpeg4</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/b5ed9e7100e2.mp4
</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;
        }
    }
}

回答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 
        }
      }


来源:https://stackoverflow.com/questions/21614684/android-simple-xml-sax-parser-displays-same-data-over-and-over

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!