Android/예제 | Posted by 덩치 2013. 7. 24. 13:05

XmlPullParser를 이용한 파싱 예제

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

14년 1월 17일 수정내용 ----- 예제 프로젝트 실행이 안된다고 해서 알아보니 다른 패키지가 섞여있었네요.

weather 패키지 삭제한 상태이며 정상작동합니다.



net2.zip



사용한 기능 - XmlPullParser , AlertDialog 등등


매니패스트 퍼미션은 

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

추가입니다.


InputStreamReader로 웹사이트 내용을 읽어와 URL로 넘겨주고

XmlPullParser를 이용해 한경닷컴 뉴스 제목과 내용을 파싱



MainActivity.java


package com.example.net2;


import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.StringReader;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.ArrayList;


import org.xmlpull.v1.XmlPullParser;

import org.xmlpull.v1.XmlPullParserFactory;


import android.app.Activity;

import android.app.AlertDialog;

import android.app.AlertDialog.Builder;

import android.content.DialogInterface;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

import android.view.View;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.ArrayAdapter;

import android.widget.Button;

import android.widget.EditText;

import android.widget.ListView;

import android.widget.Toast;


public class MainActivity extends Activity {

private Builder listDialog;

EditText urltest;

String urlStr,tv,readLine,item;

String tagName,title,body,link = null;

ListView screen;

StringBuffer sb;

Button bt;

int eventType;

XmlPullParser xpp;

XmlPullParserFactory factory;

AlertDialog.Builder dialogBuilder;

ArrayList<String> arrList,arrList2;

ArrayAdapter<String> adapter,adapter2;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);

bt = (Button)findViewById(R.id.bt);

screen = (ListView)findViewById(R.id.screen);

urltest = (EditText)findViewById(R.id.urltest);


arrList = new ArrayList<String>();

arrList2 = new ArrayList<String>();

adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,arrList);

screen.setAdapter(adapter);

dialog();

urltest.setOnLongClickListener(new View.OnLongClickListener() {

@Override

public boolean onLongClick(View arg0) { //주소창을 길게 터치하면 다이얼로그창 뷰

dialog();

return false;

}});

screen.setOnItemClickListener(new OnItemClickListener() {  //리스트 목록을 터치하면 이벤트 실행

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

dialogBuilder.setTitle(parent.getItemAtPosition(position).toString());

       dialogBuilder.setMessage(arrList2.get(position).toString());

       dialogBuilder.setPositiveButton("확인", null);

       dialogBuilder.show();

}});

bt.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

adapter.clear(); //어뎁터,리스트를 초기화시켜 새로운 데이터를 받음

arrList.clear();

adapter.notifyDataSetChanged(); //이까지. 초기화된걸 어뎁터로 리스트와 연결시켜줌

urlStr = urltest.getText().toString();

NetworkThread thread = new NetworkThread(); //스레드 선언과 호출

thread.setDaemon(true); //이거해줘야 종료될때 스레드가 죽는다는데 잘모르겠음

thread.start();

}});}


class NetworkThread extends Thread {

public void run() {

stream();

}}

Handler handler = new Handler(){

public void handleMessage(Message msg){

if(msg.what ==0){

adapter.notifyDataSetChanged();

}}};

public void parsing(){

try{

factory = XmlPullParserFactory.newInstance();

factory.setNamespaceAware(true);

xpp = factory.newPullParser();

xpp.setInput(new StringReader (tv.trim()));

eventType = xpp.getEventType();

while (eventType != XmlPullParser.END_DOCUMENT){ //최초 title테그안에 쓸데없는 내용이 있어서 추가해줬음. 

if(eventType == XmlPullParser.START_TAG){             //ex)RSS 한경닷컴어쩌구저쩌구 제목과상관없는내용

String tagName2 = xpp.getName();

if(tagName2.equals("item")){ //아이템 테그 이후부터 검색시작

while (eventType != XmlPullParser.END_DOCUMENT){

if(eventType == XmlPullParser.START_TAG){ //스타트테그를 만나면 테그값 저장

tagName = xpp.getName();

}

else if(eventType == XmlPullParser.TEXT){ //스타트테그가 아니라 텍스트일경우

if(tagName!=null){ //텍스트가 쓰래기값인경우를 배제

if(tagName.equals("title")){ //필요한건 타이틀과 본문이기때문에 스타트테그는 타이틀일때 실행

title = xpp.getText().trim();

if (title.length() > 0) { //여기도 한경닷컴특성상 제목 \n 공백 \n 제목 이런식으로돼있어서 추가

arrList.add(title);

}

}else if(tagName.equals("description")){  //스타트테그가 타이틀이 아니라 본문이면 마찬가지로 수행

link = xpp.getText().trim();

if(link.length()>0){

arrList2.add(link);

}}}}

eventType = xpp.next();

}}}

eventType = xpp.next();

}

}catch (Exception e){}}

public void stream(){  //홈페이지 정보를 읽어들여 파서로 넘겨주기위한 매서드

HttpURLConnection urlConnection = null;

try {

URL url = new URL(urlStr);

urlConnection = (HttpURLConnection) url.openConnection(); //url 연결

InputStream in = urlConnection.getInputStream(); //url내용을 비트형으로읽어옴

InputStreamReader isr = new InputStreamReader(in); // 뭐더라 다시 리더로 변환해주는과정

BufferedReader buf = new BufferedReader(isr); //줄단위로 읽어주기위해 실행

sb = new StringBuffer(); //buf의 한줄 한줄 값을 입력받아 한꺼번에 출력시키기 위해 사용


while (true) {

readLine = buf.readLine();

if (readLine == null) //읽어올 값이 없으면

break; //멈춤 그렇지않으면

sb.append(readLine); //스트링버퍼에 리드라인 내용 계속 추가

sb.append("\n"); //이게없으면 줄바꿈이없어서 알아보기가힘듦. buf의 줄바꿈단위마다 실행

}

tv = sb.toString();

parsing();


handler.sendEmptyMessage(0); //핸들러호출

}

catch (Exception e) {

}

finally {

if (urlConnection != null) {

urlConnection.disconnect();

}}}

public void dialog(){ //다이얼로그 메시지 출력부

final String[] items = {"증권","경제/금융","부동산","산업","국제","정치","사회","스포츠/문화","사설/칼럼"}; //다이얼로그에 리스트 추가

listDialog = new AlertDialog.Builder(this); //다이얼로그 선언

listDialog.setTitle("목차").setItems(items, new DialogInterface.OnClickListener() { //다이얼로그 내에 items값을 갖는 리스트 추가

@Override

public void onClick(DialogInterface arg0, int val) {

// TODO Auto-generated method stub

Toast.makeText(MainActivity.this, "선택 : "+items[val], Toast.LENGTH_SHORT).show();

if(items[val].equals("증권")){  //리스트 내용을 클릭하면 그에 맞게 에디트뷰의 주소를 설정한대로 입력

urltest.setText("http://rss.hankyung.com/new/news_stock.xml");

}else if(items[val].equals("경제/금융")){  //여기서 equals로 비교하지 않고 인덱스를 받아서 하면 더 편리함

urltest.setText("http://rss.hankyung.com/new/news_economy.xml");

}else if(items[val].equals("부동산")){

urltest.setText("http://rss.hankyung.com/new/news_estate.xml");

}else if(items[val].equals("산업")){

urltest.setText("http://rss.hankyung.com/new/news_industry.xml");

}else if(items[val].equals("국제")){

urltest.setText("http://rss.hankyung.com/new/news_intl.xml");

}else if(items[val].equals("정치")){

urltest.setText("http://rss.hankyung.com/new/news_politics.xml");

}else if(items[val].equals("사회")){

urltest.setText("http://rss.hankyung.com/new/news_society.xml");

}else if(items[val].equals("스포츠/문화")){

urltest.setText("http://rss.hankyung.com/new/news_sports.xml");

}else if(items[val].equals("사설/칼럼")){

urltest.setText("http://rss.hankyung.com/new/news_column.xml");

}}

}).setNegativeButton("직접입력",null).show();

}}




activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
   <EditText
       android:id="@+id/urltest"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="http://rss.hankyung.com/new/news_economy.xml"
       android:layout_weight="4" />
   <Button
       android:id="@+id/bt"
       android:layout_width="150dp"
       android:layout_height="wrap_content"
       android:text="검색"
       android:layout_weight="1"/>
    </LinearLayout>
   
    <ListView
        android:id="@+id/screen"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>