본문 바로가기

코딩

[ListView] DOM parser로 XML 읽어와 CustomAdapter로 ListView 출력하기

DOM parser는 XML 문서를 읽기 좋은 방법이나, 장단점이 존재한다. XMLPullParser와 SAX Parser 중에서 가장 알맞는 것을 선택하도록 하자.


해당 예제는 정보가 많은 XML 문서를 자바빈 javabean 같은 클래스를 만들어 ArrayList에 저장, CustomAdapter로 ListView에 뿌려주는 과정을 보여준다. 


원리는 간단하다.

DOM parser로 xml 문서 읽기 -> ArrayList에 보관 -> CustomAdapter로 원하는 내용 뿌리기


해당 예제로 구현된 ListView는 데이터를 파싱해와 물고 있다가 특정 리스트를 터치하면 정보를 상세보기 페이지로 인텐트시킨다. 


이번 예제의 대상이 되는 XML 문서는 다음과 같다



<item>
<basic>
<p style="TEXT-ALIGN: left"><font face="돋움" color="#6c6c6c"><span id="_SESpan_StartCaret"></span>ο 위치: 마닐라 기준 북위 13도, 동경 122도<br /> ο 수도 : 마닐라<br /> ο 면적 : 약 300,000 ㎢ (한반도의 1.3배)</font></p> <p style="TEXT-ALIGN: left"><font face="돋움" color="#6c6c6c">&nbsp;&nbsp;&nbsp;- 7,107개의 도서로 구성, 전체의 65%가 산악지대, 루손(104,688&nbsp;㎢)과 민다나오 (101,999&nbsp;㎢)가 총면적의 65%차지<br /> ο 언어 : 영어, 따갈로그어 (공용)<br /> ο 인구 : 약 1억명 (인구밀도: 308명/㎢)</font></p> <p style="TEXT-ALIGN: left"><font face="돋움" color="#6c6c6c">&nbsp;&nbsp; - 주요도시: 메트로 마닐라 (1,185만: 마닐라 165만, 퀘손시 276만명), 칼루간(149만), 다바오(145만), 세부 (85만)<br /> ο 인종 :&nbsp;말레이계가 주종이며 중국, 미국, 스페인계 혼혈 다수<br /> ο 종교 : 가톨릭 83 %, 개신교 9%, 이슬람교 5% 불교 및 기타 3%<br /> ο GDP : 2012년 약 2,504</font><font face="돋움" color="#6c6c6c">억불 (1인당 GDP 2,614불)</font></p> <p>&nbsp;</p>
</basic>
<continent>아시아/태평양</continent>
<countryEnName>Philippines</countryEnName>
<countryName>필리핀</countryName>
<id>385</id>
<imgUrl>
http://www.0404.go.kr/cmm/fms/FileDown.do?atchFileId=FILE_000000000008699&fileSn=1
</imgUrl>
<wrtDt>2014-02-14</wrtDt>
</item>





<예제// CI_Activty.java>


public class CI_Activity extends ListActivity { 


final static String CI_INFO = "XML 문서의 주소";

final static String TAG = "CI_COUNTRYINFO";


CI_CustomAdapter adapter;

ProgressBar progress;

Handler handler = new Handler();

ArrayList<ItemList> infoList = new ArrayList<ItemList>();

ListView listView;


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.ci_activity);


progress = (ProgressBar)findViewById(R.id.progressBar); //프로그래스바

adapter = new CustomAdapter(this, R.layout.ci_card);    //커스텀 어뎁터와 각 row가 될 레이아웃을 호출한다. 

setListAdapter(adapter);

thread();

}

//onCreate


//쓰레드

public void ci_thread(){

progress.setVisibility(View.VISIBLE);

new Thread(){

@Override

public void run() {

final InputStream input = getStreamFromUrl();    //스트림 데이터를 선언한다. 

handler.post(new Runnable() {


@Override

public void run() {

C_parser(input); // 파서에 읽어온 url의 데이터를 집어넣는다. 

progress.setVisibility(View.GONE); // 정보를 다 읽어오면 프로그래스가 자연스럽게 사라지도록 한다.

}

});

}.start();

}


// xml Url로부터 데이터 받아오기

public InputStream getStreamFromUrl(){

InputStream input = null;

try{

HttpClient client = new DefaultHttpClient();

HttpGet getMethod = new HttpGet(ItemList);

HttpResponse response = (HttpResponse)client.execute(getMethod);

HttpEntity entity = response.getEntity();

BufferedHttpEntity buf = new BufferedHttpEntity(entity);

input = buf.getContent();


}catch(Exception e){

Log.e(TAG, "네트워크 오류", e);

}

return input;

}

public void C_Parser(InputStream input){


try{

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder(); 

Document doc = builder.parse(input);

NodeList infos = doc.getElementsByTagName("item");

//factory.setIgnoringElementContentWhitespace(true);


for(int i = 0; i < infos.getLength(); i++) {

ItemList infoCountry = new ItemList();

NodeList info = infos.item(i).getChildNodes();


for(int j = 0; j < info.getLength(); j++) {

Node n = info.item(j);

if(n.getNodeName().equals("countryName")) {

infoCountry.countryName = n.getFirstChild().getNodeValue();


}if(n.getNodeName().equals("countryEnName")) {

infoCountry.countryEnName = n.getFirstChild().getNodeValue();


}if(n.getNodeName().equals("basic")) {

infoCountry.basic = n.getFirstChild().getNodeValue();


}if(n.getNodeName().equals("id")) {

infoCountry.id = n.getFirstChild().getNodeValue();


}if(n.getNodeName().equals("imgUrl")) {

infoCountry.iimgUrl = n.getFirstChild().getNodeValue();

}

}

infoList.add(infoCountry);

}

adapter.notifyDataSetChanged(); //어뎁터를 갱신한다.



} catch(Exception e) {

Log.e(TAG, "parsing error", e);


} finally {

if(input!= null) try {input.close();} catch (IOException e) {}

}

}


/* 이벤트 핸들러 */

@Override

protected void onListItemClick(ListView list, View v, int position, long id) {

Intent intent = new Intent(this, 다음페이지.class);


//데이터 전달 //저장된 데이터 중 특정 부분을 끄집어낸다 

intent.putExtra("iimgUrl", infoList.get(position).iimgUrl);

intent.putExtra("basic", infoList.get(position).basic);

intent.putExtra("countryName", infoList.get(position).countryName);

intent.putExtra("countryEnName", infoList.get(position).countryEnName);

intent.putExtra("id", infoList.get(position).id);


startActivity(intent);

}


//커스텀 어뎁터

class CI_CustomAdapter extends BaseAdapter{


Context context;

LayoutInflater inflater;

int layout;


public CI_CustomAdapter(Context context, int layout) {

this.context = context;

this.layout = layout;


inflater = LayoutInflater.from(context); 

}


@Override

public int getCount() {

return infoList.size();

}


@Override

public Object getItem(int position) {

return infoList.get(position).countryName;

}


@Override

public long getItemId(int position) {

return position;

}


@Override

public View getView(int position, View convertView, ViewGroup parent) {


if(convertView == null) { 

convertView = inflater.inflate(layout, parent, false);

}                 


//국가명

TextView ci_countryName = (TextView)convertView.findViewById(R.id.ci_test_d_countryName);

ci_countryName.setText(infoList.get(position).countryName);

//


//이런 식으로 데이터를 꼐속 뿌리면 됨.

TextView ci_countryEnName = (TextView)convertView.findViewById(R.id.ci_test_d_countryEnName);

ci_countryEnName.setText(infoList.get(position).countryEnName);


}

}


///클래스

class ItemList{

String id;

String basic;

String countryName;

String countryEnName;

String iimgUrl;

}