【问题标题】:Parsing XML in Android (XmlPullParserException)在 Android 中解析 XML (XmlPullParserException)
【发布时间】:2015-10-29 13:07:44
【问题描述】:

我目前正在学习 Android 编程,当我尝试解析 XML 时,出现以下错误(程序运行正常,但它只解析第一个 XML 链接):

这是我的代码:

public class RSSActivity extends AppCompatActivity {

/**
 * List of feeds that has been fetched.
 */
public static ArrayList<RSSFeed> Feeds;

/**
 * Button for Seattle Times
 */
private Button mSeattleBtn;

/**
 * Button for ESPN
 */
private Button mESPNBtn;

/**
 * The layout contains the loading image
 */
private RelativeLayout mProgress;

/**
 * {@inheritDoc}
 */
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_rss);

    Feeds = new ArrayList<>();
    mProgress = (RelativeLayout) findViewById(R.id.loading);
    mProgress.setVisibility(View.GONE);

    mSeattleBtn = (Button) findViewById(R.id.seattle_times);
    mSeattleBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new DownloadXML().execute("http://www.seattletimes.com/feed/",
                    "http://www.seattletimes.com/seattle-news/feed/",
                    "http://www.seattletimes.com/nation-world/feed/");
        }
    });

    mESPNBtn = (Button) findViewById(R.id.espn_btn);
    mESPNBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new DownloadXML().execute("http://sports.espn.go.com/espn/rss/news",
                    "http://sports.espn.go.com/espn/rss/nfl/news",
                    "http://sports.espn.go.com/espn/rss/nba/news");
        }
    });

}

/**
 * Async task to fetch the XML from the internet
 */
private class DownloadXML extends AsyncTask<String, Void, String> {

    /**
     * The name of the current class, used for Log (debugging)
     */
    private static final String TAG = "DownloadXML";

    /**
     * The content of the xml that has been fetched from the internet
     */
    private String xmlContent;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        xmlContent = "";
        mSeattleBtn.setVisibility(View.GONE);
        mESPNBtn.setVisibility(View.GONE);
        mProgress.setVisibility(View.VISIBLE);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String doInBackground(String... params) {

        // set the xml contents to xmlContent
        //xmlContent = getXMLContent(params[0]);
        for (String s: params) {
            xmlContent += getXMLContent(s);
        }

        // This will return the xmlContent to the onPostExecute method.
        return xmlContent;
    }

    /**
     * Perform the actual downloading process of the RSS
     * file here.
     *
     * @param path the url path of the rss feed.
     * @return the completed download xml file (converted to String)
     */
    private String getXMLContent(String path) {
        StringBuilder temp = new StringBuilder();

        try {

            // Open the connection
            URL url = new URL(path);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            InputStream inputStream = con.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

            int charToRead;
            // reading 1000 bytes at a time.
            char[] input = new char[1000];

            // Keep reading the file until there's no more bytes(chars) left to read
            while(true) {
                charToRead = inputStreamReader.read(input);
                if(charToRead <= 0) {
                    break;
                }
                temp.append(String.copyValueOf(input, 0, charToRead));
            }

            return temp.toString();

        } catch (IOException e) {
            Log.d(TAG, "Error: " + e.getMessage());
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        RSSFeed curFeed = null;
        boolean inItem = false;
        String value = "";

        try {
            // Instantiate XmlPullParser
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            // specify that the code will be supported by XML namespaces
            factory.setNamespaceAware(true);
            XmlPullParser parser = factory.newPullParser();
            parser.setInput(new StringReader(result));
            int event = parser.getEventType();

            // Parse the XML content
            while(event != XmlPullParser.END_DOCUMENT) {
                String tag = parser.getName();

                // Only parse with the starting and ending tag of "item"
                // and every tags inside it, ignore other tags.
                switch(event) {
                    case XmlPullParser.START_TAG:
                        // if the begin tag is item which mean
                        // we can begin to to fetch the xml tags we want into our application
                        if(tag.equalsIgnoreCase("item")) {
                            inItem = true;
                            curFeed = new RSSFeed();
                        }
                        break;
                    case XmlPullParser.TEXT:
                        value = parser.getText();
                        break;
                    case XmlPullParser.END_TAG:
                        /*
                            while reach the end tag of the current tag
                            if the end tag is title then set it to the current feed title,
                            if the end tag is link then set it to the current feed link,
                            if the end tag is pubdate then set it to the current feed pubdate,
                            if the end tag is item we know that there's no more contents to add
                            to the current feed so we move on to parse another feed.
                         */
                        if(inItem){
                            if (tag.equalsIgnoreCase("title")) {
                                curFeed.setTitle(value);
                            } else if (tag.equalsIgnoreCase("link")) {
                                curFeed.setLink(value);
                            } else if (tag.equalsIgnoreCase("pubdate")) {
                                curFeed.setDate(value);
                            } else if (tag.equalsIgnoreCase("item")) {
                                Feeds.add(curFeed);
                                inItem = false;
                            }
                        }
                        break;
                    default:

                }

                event = parser.next();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        findViewById(R.id.loading).setVisibility(View.GONE);
        Intent intent = new Intent(RSSActivity.this, FeedListActivity.class);
        startActivity(intent);
        finish();

    }
}
}

由于我对所有这些都是新手,有人可以向我解释一下这里发生了什么吗?看起来错误来自解析器。

编辑:如果我只向 Asynctask.execute() 传递一个参数,那么一切运行正常。

解决方案:

现在唯一的解决方案是按照 nikhil.thakkar

的回复依次处理每个 URL

那么我建议你串行处理每个 url..

【问题讨论】:

  • 我认为你的 xml 有问题。能否请您也粘贴xml。
  • xml的链接在setOnClickListener()的匿名类中
  • 你能打印临时变量并将内容粘贴到字符串中吗?
  • 内容太长,无法粘贴到这里,但好像打印出XML内容。

标签: java android xml xmlpullparser


【解决方案1】:

请检查 onPostExecute 方法。您正在访问 XML 文件中不存在的令牌。

【讨论】:

  • 嗨,我刚刚仔细检查了 XML 链接,每个 RSS 提要都以item 标记开头,每个item 标记中都有linktitlepubdate 标记。如果这是你的意思,否则我还是不明白你刚才说的话,对不起。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多