SELECT * FROM Vzakladke.net

Статьи об автоматизации и программировании

SAX parser example on Android

 

 

SAX - это событийный парсер для XML, т.е. он последовательно читает и рабирает данные из входного потока (это может быть файл, сетевое соединение, или любой другой InputStream). Когда парсер находит структурный элемент (открывающий тег, закрывающий тег, и т.п.), он оповещает об этом слушателя, и передает ему в качестве параметра найденый элемент. Слушатель делает все необходимые операции для данного элемента.

перейдем к нашему вопросу - как написать простейший парсер на Android.

Прежде всего необходимо описать в манифесте доступ к интернет-соединению:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
 

 

Опишем разметку для activity_main.xml - в главном лэйауте будет ListView.

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/lvPcsPost"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin" />

 

И разметку для отдеьного элемента list_item_post.xml 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

    <TextView
        android:id="@+id/tvTitle"
        style="?android:textAppearanceMedium"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="2"
        android:textColor="#ff5a595b" />

    <TextView
        android:id="@+id/tvPublishDate"
        style="?android:textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textColor="#ff80cbc4" />

</LinearLayout>

 

Перепишем главное активити MainActivity.java с таким кодом:

package com.example.saxparse;


import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;

import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import java.util.ArrayList;

public class MainActivity extends Activity {

    ListView lvPcsPost;
    ArrayList<PostValue> postValueArrayList;

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

        lvPcsPost = (ListView) findViewById(R.id.lvPcsPost);
        lvPcsPost.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView< ? > parent, View view, int position, long id) {
                if (postValueArrayList != null && postValueArrayList.size() > 0) {
                    Intent intentShowPost = new Intent(Intent.ACTION_VIEW, Uri.parse(postValueArrayList.get(position).getGuid()));
                    startActivity(intentShowPost);
                }
            }
        });
        new PostAsync().execute();
    }

    class PostAsync extends AsyncTask<Void, Void, Void> {
        ProgressDialog pd;
        XMLHelper helper;


        @Override
        protected void onPreExecute() {
            pd = ProgressDialog.show(MainActivity.this, "Wait!", "Loading ...", true, false);
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            helper = new XMLHelper();
            helper.get();
            postValueArrayList = helper.getPostsList();
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            PostBaseAdapter postBaseAdapter = new PostBaseAdapter(MainActivity.this, postValueArrayList);
            lvPcsPost.setAdapter(postBaseAdapter);
            pd.dismiss();
        }

    }

}

 

Далее очень важный файл XMLHelper.java - это обработчик событий SAX, где идет перебор нужных нам элементов:

package com.example.saxparse;

import android.util.Log;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class XMLHelper extends DefaultHandler {
    /**
     * The URL to be parsed
     */
    private String URL_MAIN = "http://asksql.org/?format=xml";
    String TAG = "XMLHelper";

    Boolean currTag = false;
    String currTagVal = "";
    private PostValue post = null;
    private ArrayList<PostValue> posts = new ArrayList<PostValue>();

    public ArrayList<PostValue> getPostsList() {
        return this.posts;
    }


    public void get() {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser mSaxParser = factory.newSAXParser();
            XMLReader mXmlReader = mSaxParser.getXMLReader();
            mXmlReader.setContentHandler(this);
            InputStream mInputStream = new URL(URL_MAIN).openStream();
            mXmlReader.parse(new InputSource(mInputStream));
        } catch (Exception e) {
            // Exceptions can be handled for different types
            // But, this is about XML Parsing not about Exception Handling
            Log.e(TAG, "Exception: " + e.getMessage());
        }
    }

    // This method receives notification character data inside an element
    // e.g. <post_title>Add EditText Pragmatically - Android</post_title>
    // It will be called to read "Add EditText Pragmatically - Android"
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        if (currTag) {
            currTagVal = currTagVal + new String(ch, start, length);
            currTag = false;
        }
    }

    // Receives notification of end of element
    // e.g. <post_title>Add EditText Pragmatically - Android</post_title>
    // It will be called when </post_title> is encountered
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        currTag = false;

        if (localName.equalsIgnoreCase(("title"))
            post.setTitle(currTagVal);

        else if (localName.equalsIgnoreCase("guid"))
            post.setGuid(currTagVal);

        else if (localName.equalsIgnoreCase("date"))
            post.setDate(currTagVal);

        else if (localName.equalsIgnoreCase("post"))
            posts.add(post);
    }

    // Receives notification of start of an element
    // e.g. <post_title>Add EditText Pragmatically - Android</post_title>
    // It will be called when <post_title> is encountered
    @Override
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes) throws SAXException {
        Log.i(TAG, "TAG: " + localName);

        currTag = true;
        currTagVal = "";
        // Whenever <post> element is encountered it will create new object of PostValue
        if (localName.equals("post"))
            post = new PostValue();
    }
}

Большая часть кода заключена в обработчике, что характерно для любого SAX-парсера. Обработчик получает уведомления о событиях от парсера по мере того, как тот разбирает документ XML.

 

Заметим сразу, что ответ должен быть в XML формате, но должен быть именно в такой упрощенной форме (ничего лишнего добавлять здесь не нужно):

<posts>
<post>
<title>
SAX Parse Andriod Application Project
</title>
<guid>http://www.asksql.org/?p=657</guid>
<date>2015-10-25 01:46:20</date>
</post>
<post>
<title>
Create Andriod Application Project in Android Studio
</title>
<guid>http://www.asksql.org/?p=655</guid>
<date>2015-09-29 12:17:25</date>
</post>
</posts>

 

Далее создаем класс PostValue геттеров и сеттеров принимаемых значений

package com.example.saxparse;

/**
 * A class for getters and setters for post
 */
public class PostValue {
    String title, guid, date;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getGuid() {
        return guid;
    }

    public void setGuid(String guid) {
        this.guid = guid;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

}

 

Потребуется еще и класс PostBaseAdapter  

 

package com.example.saxparse;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;


public class PostBaseAdapter extends BaseAdapter {

    private LayoutInflater layoutInflater;
    private ArrayList<PostValue> postValueArrayList;

    public PostBaseAdapter(Context context, ArrayList<PostValue> postValueArrayList) {
        this.layoutInflater = LayoutInflater.from(context);
        this.postValueArrayList = postValueArrayList;

    }

    @Override
    public int getCount() {
        return postValueArrayList.size();
    }

    @Override
    public PostValue getItem(int position) {
        return postValueArrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.list_item_post, parent, false);
            viewHolder = new ViewHolder(convertView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        PostValue postValue = getItem(position);

        viewHolder.tvTitle.setText(postValue.getTitle());
        viewHolder.tvPublishDate.setText(postValue.getDate());

        return convertView;
    }

    private class ViewHolder {
        TextView tvTitle, tvPublishDate;

        public ViewHolder(View item) {
            tvTitle = (TextView) item.findViewById(R.id.tvTitle);
            tvPublishDate = (TextView) item.findViewById(R.id.tvPublishDate);
        }
    }
}

 

 

 

Дата публикации: 2015-06-01 18:07:12

JAVA, Android

0

Отзывы:

Ваше имя:

Ваш e-mail (необязательно):

Сообщение:

Captcha