【问题标题】:how to read XML file from a URL using XmlPullParser, AsyncTask Android如何使用 XmlPullParser、AsyncTask Android 从 URL 读取 XML 文件
【发布时间】:2014-10-09 15:34:45
【问题描述】:

我已关注this link

日志猫

warning : org.xmlPull.v1.XmlPullParserException : expected : START_TAG { null } rss (position:START_TAG <html>@2:7 in java.io.InputStreamReader @41232f00)<br/> error : NullPoiterException

我一直在寻找并使用一些基本的测试方法,但 readRss 方法中的 parser.require 不能运行到 rss 标签
我想将标题和链接标签的内容检索到项目中
我对我的英语能力感到抱歉,而且我是安卓编程新手
非常感谢!

来自 url 的 xml 内容

<rss xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
  <channel>
    <title></title>
    <description></description>
    <pubDate></pubDate>
    <generator></generator>
    <link></link>

    <item>
      <title>CONTENTS</title>
      <link>http://test.html/</link>
    </item>

  </channel>
</rss>

XmlParser 代码

public class XmlParser {

private static final String nameSpace = null;

public XmlParser(){

}

public List<Item> parse(InputStream inputStream)
        throws XmlPullParserException, IOException {
    try {
        XmlPullParser parser = Xml.newPullParser();
        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
        parser.setInput(inputStream, null);
        parser.nextTag();
        return readRss(parser);
    } finally {
        inputStream.close();
    }
}

private List<Item> readRss(XmlPullParser parser)
        throws XmlPullParserException, IOException {
    List<Item> itemList = new ArrayList<Item>();
    int eventType = parser.getEventType();

    System.out.println(parser.getName(); // <==== position is   html

    parser.require(XmlPullParser.START_TAG, nameSpace, "rss");  // <---- error
       /** Code in here is failed**/

    while (parser.next() != XmlPullParser.END_TAG) {
        if (eventType!= XmlPullParser.START_TAG) {
            continue;
        }
        String name = parser.getName();

        // Starts by looking for the Rss tag
        if (name.equals("item")) {
                itemList.add(readItem(parser));
        } else {
            skip(parser);
        }
    }
    return itemList;
}

// This class represents a single entry (post) in the XML feed.
// It includes the data members "title," "link," and "summary."
public static class Item{
    String title = "";
    String link = "";

    private Item() {
    }
    private Item(String title){
        this.title = title;
    }

    private Item(String title, String link) {
        this.title = title;
        this.link = link;
    }
}

// Parses the contents of an item. If it encounters a title, link tag, hands
// them
// off
// to their respective &quot;read&quot; methods for processing. Otherwise,
// skips the tag.

private Item readItem(XmlPullParser parser) throws XmlPullParserException,
        IOException {
    parser.require(XmlPullParser.START_TAG, nameSpace, "item");
    String title = null;
    String link = null;
    while (parser.next() != XmlPullParser.END_TAG) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }
        String name = parser.getName();
        if (name.equals("title")) {
            title = readTitle(parser);
        /*} else if (name.equals("link")) {
            link = readLink(parser);*/
        }else{
            skip(parser);
        }
    }
    return new Item(title);
    //return new Item(title, link);
}

// Skips tags the parser isn't interested in. Uses depth to handle nested tags. i.e.,
// if the next tag after a START_TAG isn't a matching END_TAG, it keeps going until it
// finds the matching END_TAG (as indicated by the value of "depth" being 0).

private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
    if(parser.getEventType() != XmlPullParser.START_TAG){
        throw new IllegalStateException();
    }
    int depth = 1;
    while(depth != 0){
        switch (parser.next()) {
        case XmlPullParser.END_TAG:
            depth--;
            break;
        case XmlPullParser.START_TAG:
            depth++;
            break;
        }
    }   
}

// Processes title tags in the Rss.
private String readTitle(XmlPullParser parser)
        throws XmlPullParserException, IOException {
    parser.require(XmlPullParser.START_TAG, nameSpace, "title");
    String title = readTitle(parser);
    parser.require(XmlPullParser.END_TAG, nameSpace, "title");
    return title;
}

// Processes link tags in the Rss.
/*private String readLink(XmlPullParser parser)
        throws XmlPullParserException, IOException {
    parser.require(XmlPullParser.START_TAG, nameSpace, "link");
    String link = readLink(parser);
    parser.require(XmlPullParser.END_TAG, nameSpace, "link");
    return link;
}

}

列表活动代码

public class MainActivity extends ListActivity {

static final String URL = "http://vnexpress.net/rss/du-lich.rss";
ArrayAdapter<Item> arrAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new buildDataXml().execute(URL);
}

private class buildDataXml extends AsyncTask<String, Void, List<Item>> {
    @Override
    protected List<Item> doInBackground(String... params) {
        try {
            return loadXmlFromUrl(params[0]);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected void onPostExecute(List<Item> result) {
        super.onPostExecute(result);
        System.out.println(result.get(0));
        arrAdapter = new ArrayAdapter<Item>(getApplicationContext(), android.R.layout.simple_list_item_1, result);
        setListAdapter(arrAdapter);
    }
}

private List<Item> loadXmlFromUrl(String strUrl) throws XmlPullParserException, IOException{
    InputStream inputStream = null;
    List<Item> item = null;
    XmlParser parser = new XmlParser();

    try {
        inputStream = downloadUrl(strUrl);
        System.out.println("InputStream : "+inputStream.available());

        item = parser.parse(inputStream);
        System.out.println("Item Size : " + item.size());

    // Makes sure that the InputStream is closed after the app is
    // finished using it.
    } finally {
        if (inputStream != null) {
            inputStream.close();
        }
    }

    return item;
}

private InputStream downloadUrl(String strUrl) throws IOException{
    URL url = new URL(strUrl);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setReadTimeout(10000 /* milliseconds */);
    conn.setConnectTimeout(15000 /* milliseconds */);
    conn.setRequestMethod("GET");
    conn.setDoInput(true);
    conn.setRequestProperty("Content-Type", "application/xml");
    // Starts the query
    conn.connect();
    InputStream stream = conn.getInputStream();
    return stream;
}

【问题讨论】:

    标签: android xml android-asynctask xmlpullparser rss-reader


    【解决方案1】:

    您的 Http 请求没有像您期望的那样返回 rss,而是返回了一个 HTML 页面,这就是您的解析失败的原因

    返回的内容片段

    <!DOCTYPE html>
    <html><!-- InstanceBegin template="/Templates/common.dwt" codeOutsideHTMLIsLocked="false" -->
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-title" content="Vnexpress.net" />
    <!-- iPad icons -->
    <link rel="apple-touch-icon-precomposed" href="http://st.f1.vnecdn.net/responsive/images/logos/72x72.png" sizes="72x72">
    <link rel="apple-touch-icon-precomposed" href="http://st.f1.vnecdn.net/responsive/images/logos/114x114.png" sizes="144x144">
    <!-- iPhone and iPod touch icons -->
    <link rel="apple-touch-icon-precomposed" href="http://st.f1.vnecdn.net/responsive/images/logos/57x57.png" sizes="57x57">
    <link rel="apple-touch-icon-precomposed" href="http://st.f1.vnecdn.net/responsive/images/logos/114x114.png" sizes="114x114">
    <!-- Nokia Symbian -->
    <link rel="nokia-touch-icon" href="http://st.f1.vnecdn.net/responsive/images/logos/57x57.png">
    <!-- Android icon precomposed so it takes precedence -->
    <link rel="apple-touch-icon-precomposed" href="http://st.f1.vnecdn.net/responsive/images/logos/114x114.png" sizes="1x1">
    <!-- InstanceBeginEditable name="doctitle" -->
    <title>Tin nhanh VnExpress - Äá»c báo, tin tức online 24h</title>
    <!-- InstanceEndEditable -->
    <link rel="stylesheet" href="http://st.f3.vnecdn.net/responsive/c/v2/general.css" media="all" />
    <!-- link rel="stylesheet" href="http://st.f3.vnecdn.net/responsive/css/iphone.css" media="all" / -->
    <!-- InstanceBeginEditable name="css" -->
    <!-- InstanceEndEditable -->
    <script src="http://st.f4.vnecdn.net/responsive/libs/jquery-1.7.1.min.js"></script>
    <script language="javascript" type="text/javascript">
             var interactions_url    = 'http://interactions.vnexpress.net';
             var base_url            = 'http://vnexpress.net';
             var css_url             = 'http://st.f3.vnecdn.net/responsive/c/v2';
             var js_url              = 'http://st.f2.vnecdn.net/responsive/j/v2';
             var flash_url           = 'http://st.f4.vnecdn.net/responsive/f/v2';
             var img_url             = 'http://st.f1.vnecdn.net/responsive/i/v2';
             var image_cloud         = 'http://l.f29.img.vnecdn.net';
             var PageHot             =  0;
             var device_env          =  2;
             var site_id             =  1000000;
             var SITE_ID             =  1000000;
             var PAGE_FOLDER         =  1001005;
             var PAGE_DETAIL         =  0         //setTypingMode(1);
          </script>
    <script src="http://st.polyad.net/library/2014/VneShowAds.js"></script>
    <script src="http://st.polyad.net/library/2014/vneads.js"></script>
    <script type="text/javascript" src="http://st.f2.vnecdn.net/responsive/j/v2/utils/utils.js"></script>
    <script type="text/javascript" src="http://st.f2.vnecdn.net/responsive/j/v2/utils/crawler.js"></script>
    
    <script type="text/javascript" src="http://st.f2.vnecdn.net/responsive/j/v2/interactions/parser_v2.js"></script>
    <script language="javascript" type="text/javascript">
             var PageHot             =  0;
             var site_id             =  1000000;
             var PAGE_FOLDER         =  1001005;
    </script>
    
    <!-- InstanceBeginEditable name="javascript" -->
    <!-- InstanceEndEditable -->
    <!-- TRACKING GOOGLE -->
            <script>
              (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
              (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
              m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
              })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
            //beta vnexpress reponsive
              ga('create', 'UA-249346-69', 'vnexpress.net');
              ga('send', 'pageview');
            //new tracker
              ga('create', 'UA-249346-21', 'auto', {'name': 'newTracker'});
              ga('newTracker.send', 'pageview');
    
            //new tracker 1
              ga('create', 'UA-249346-22', 'auto', {'name': 'newTracker1'});
              ga('newTracker1.send', 'pageview');
            </script>
          <script type="text/javascript">
             /*
             var _gaq = _gaq || [];
             _gaq.push(['_setAccount', 'UA-249346-21']);
             _gaq.push(['_trackPageview']);
    
             _gaq.push(['b._setAccount', 'UA-249346-22']);
             _gaq.push(['b._trackPageview']);
    
             _gaq.push(['c._setAccount', 'UA-249346-1']);
             _gaq.push(['c._trackPageview']);
             <?php echo $this->ShowGaByCate($parent_category_id);?>
    
             (function() {
             var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
             ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
             var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
             })();
             */
          </script>
          <script>
            if(PAGE_FOLDER==1000000)
            {
                var _siteId="6";
                /// track cu trang chu//
    
                   (function(){
                    var e=document.createElement("script");e.type="text/javascript",e.async=!0,e.src="http://st.l.a.eclick.vn/ea.js";
                    var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)})();
             }else
             {
                  var _siteId = "5";
                  // track cu trang con //  
                   (function(){
                    var e=document.createElement("script");e.type="text/javascript",e.async=!0,e.src="http://st.l.a.eclick.vn/ea.js";
                    var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)})();
             }
            </script>
          <!-- END TRACKING GOOGLE -->
    </head>
    
    <body>
    <div class="block_more_info" id="box_col_left" style="left: -240px;">
       <div class="box_width_common">
          <div class="btn_control_col_left"><img alt="" src="http://st.f1.vnecdn.net/responsive/i/v2/graphics/img_left_panel.gif"></div>
          <div class="block_scoll_menu">
             <div class="block_search">
                <form id="search" target="_blank" method="get" 
    ....
    

    编辑: 在更好地查看您的代码之后,您似乎认为 parser:require 将 xml 元素直到 rss 元素,但事实并非如此 require 验证解析器是否当前事件匹配指定的命名空间,如果提供匹配提供的命名空间和元素名称(如果事件是START_TAGEND_TAG

    在查看 HTTP 流量后,我发现您的请求被重定向到错误页面

    GET /rss/du-lich.rss HTTP/1.1
    Content-Type: application/rss+xml
    User-Agent: Dalvik/2.0.0 (Linux; U; Android L Build/LPV81B)
    Host: vnexpress.net
    Connection: Keep-Alive
    Accept-Encoding: gzip
    
    HTTP/1.1 302 Moved Temporarily
    Server: Fengine/1.5.2
    Date: Fri, 10 Oct 2014 09:20:56 GMT
    Content-Type: text/html
    Transfer-Encoding: chunked
    Set-Cookie: device_env=1; expires=Fri, 17-Oct-2014 09:20:55 GMT; path=/; domain=vnexpress.net
    Location: /error4.html
    Content-Encoding: gzip
    Vary: Accept-Encoding
    server: web_141.173
    

    所以我进一步调查发现HTTP server 可能基于User agent 限制访问,以下行似乎解决了这个问题

    conn.setRequestProperty("User-Agent", "Fiddler");   
    

    修复了这个问题,我相信这是一个很好的起点,您可以继续并修复您遇到的解析错误

    结束编辑

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多