XML Parser 6 조 20080945 이성훈 20081005 이재환 20111519 김기순
목차 1. Parsing의정의, 필요성 2. DOM Parser 3. SAX Parser 4. XML Pull Parser
1. Parsing 의정의, 필요성
Parsing 이란? 주어진문장을분석하거나문법적관계를해석하는것 Parsing 의필요성 프로그래밍이간편 플랫폼독립적프로그래밍언어에구애받지않음 필요한데이터를빠르게처리가능 웹상의 XML이수정되어도프로그램을변경하지않아도됨
2. DOM Parser
DOM 파서란? 문서의모든내용을해석한후메모리에트리구조로펼친후읽어들임 트리구조 < 학생 > < 이름 > 홍길동 </ 이름 > < 학번 >12345678</ 학번 > < 학년 >2 학년 </ 학년 > </ 학생 > 학생 이름학번학년
DOM 파서장단점 장점 특정노드에대한임의접근이자유롭다. 원하는노드를몇번이고읽을수있다. 문서의수정도가능하다. 단점 메모리사용이많다. 처음시작이다소느리다. ( 문서전체를로딩해야하므로 )
설명 XML 문서를열기위한최초작업 1. DocumentBuilderFactory 객체생성 생성방법 : 정적 (static) 메소드 newinstance() 를통해생성 생성예 : DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 2. DocumentBuilder 객체생성 생성방법 : newdocumentbuilder() 메소드를통해생성 생성예 : DocumentBuilder builder = factory.newdocumentbuilder(); 두작업을마쳤다면이제 XML 문서를파싱할준비가끝남
설명 앞서만든 builder 객체로 parse() 메소드호출 Document parse (InputStream stream) Document parse (String URI) Document parse (File file) 매개변수 작성예 : Document doc = builder.parse(stream); 1. Parse() 메소드는받은문서를분석하여메모리에트리형태로전개 2. 트리구조정보를담고있는 Document 객체반환
접근방법 Document 객체를얻었다면요소에빠른속도로접근할수있다. Document 객체 학생 이름 이름 이름 학년 이성훈이재환김기순 4 학년
접근방법 Document 객체내루트엘리먼트에접근하기위한메소드 Element getdocumentelement() 사용예 : Element root = doc.getdocumentelement(); Document 객체 접근 학생 이름 이름 이름 학년 이성훈이재환김기순 4 학년
접근방법 루트에서태그명과일치하는모든자식요소를찾는메소드 NodeList getelementsbytagname( 태그명 ) 사용예 : NodeList childs = root.getelementsbytagname( 이름 ); Document 객체 학생 접근 이름 이름 이름 학년 이성훈이재환김기순 4 학년
접근방법 노드리스트에서하나의요소를선택하는방법 노드리스트.item( 번호 ) 접근예 : Node child = childs.item(0) Document 객체 학생 접근 이름 이름이름학년 이성훈이재환김기순 4 학년 첫번째이름요소에접근
접근방법 요소의내용에접근 노드명.getFirstChild() 접근예 : Node childvalue = child.getfirstchild() Document 객체 학생 이름 학번 2008.. 접근 이성훈 DOM 에서는요소의내용값을요소의자식노드로취급한다. ( 단, 요소의속성은위규칙을따르지않는다. 위그림에서는학번에해당 )
접근방법 요소의모든속성에접근하는메소드 NamedNodeMap getattributes() 사용예 : NamedNodeMap Attrs= child.getattributes() Document 객체 학생 학번 이름 이성훈 2008.. 주소 대구.. 접근
접근방법 속성목록에서하나의속성에접근하는방법 속성목록.item( 번호 ) 사용예 : Node attr= Attrs.item(0) Document 객체 학생 이름 이성훈 학번 2008.. 주소대구.. 접근
접근방법 그밖의노드관련주요메소드 String getnodename() 노드이름 Short getnodetype() 노드타입 String getnodevalue() 노드값노드의이름, 타입, 값반환 Node getfirstchild() 첫번째자식노드 Node getlastchild() 마지막자식노드 Node getnextsibling() 자신의다음노드 Node getprevioussibling() 자신의이전노드 Node getparentnode() 자신의부모노드 NodeList getchildnodes() 모든자식노드노드를중심으로주변노드를찾는메소드
예제수행 버튼을누르면 XML 문서를파싱하는프로그램 루트요소 자식요소 속성 내용 메모장으로 student.xml 작성
예제수행환경 이클립스에서안드로이드프로젝트생성후 res raw 디렉터리에저장
예제수행환경 버튼하나와텍스트뷰로이루어진리니어레이아웃
코드작성 버튼의 onclick 리스너안에 DOM 파싱코드작성
코드작성 1 2 문서를읽어트리형태로통합된 Document 객체를얻는과정
예제수행 이쯤에서다시보는 student.xml 루트요소 자식요소 속성 내용
코드작성 이제 Student.xml 의각요소값을출력해보자.
실행결과 Parse XML 버튼을누르면내용출력
실제웹문서파싱해보기 한경닷컴 http://rss.hankyung.com/ 파싱할임의의뉴스선택
실제웹문서파싱해보기 마우스오른쪽버튼클릭 소스보기선택
실제웹문서파싱해보기 XML 문서출력
실제웹문서파싱해보기 루트요소 필요한부분 문서의구조를파악하고가져올부분을정함
실제웹문서파싱해보기 이문서의구조를간단히나타내면 루트요소 필요한부분 <?xml version="1.0" encoding="utf-8"?> <rss version="2.0"> <item> <title> 헤드라인 </title> </item> <item> </item> <item> </item> 접근방법을생각해보자
실제웹문서파싱해보기 Document 구조 rss < 접근절차 > 1. 루트요소 rss 에접근 item item item 그외 title title title 2. item 태그명을가진요소접근 3. item 요소내의자식요소중 title 요소접근 4. title 요소의내용접근 헤드라인헤드라인헤드라인
예제수행환경 버튼하나와리스트뷰로이루어진리니어레이아웃
예제수행환경 AndroidManifest.xml 파일에아래코드추가 < 주의 > 안드로이드버전이허니콤 (3.0) 이상일경우 메인쓰레드에선웹문서파싱이불가능 1. 이클립스에서작업버전을낮추거나 2. 별도의쓰레드를만들어파싱코드작성
코드작성 코드중엘리먼트접근부분 루트요소접근 Item 요소접근 Title 요소의내용접근
실행결과 헤드라인조회버튼을누르면내용출력
MainActivity 코드 ( 첫번째예제 ) import java.io.inputstream; import javax.xml.parsers.*; import org.w3c.dom.*; import android.os.bundle; import android.app.activity; import android.content.res.resources; import android.view.*; import android.widget.*; public class MainActivity extends Activity { TextView mresult; @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); mresult = (TextView)findViewById(R.id.result); public void monclick(view v){ try{ // xml 문서를파싱하기위한준비 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newdocumentbuilder(); Element root = doc.getdocumentelement(); // 루트엘리먼트 NodeList childs = root.getelementsbytagname("name"); // 루트엘리먼트에서 name 이란이름을가진요소전체 Node child = childs.item(0); // 첫번째 name 요소 NamedNodeMap Attrs = child.getattributes(); // name 의속성값 Node attr = Attrs.item(0); // name 의첫번째속성 Node childvalue = child.getfirstchild(); // 내용도하나의자식으로취급 String rootname = root.getnodename(); // 루트명 String childname = child.getnodename(); // 자식요소명 String childvalue = childvalue.getnodevalue(); // 자식요소값 String AttrName = attr.getnodename(); // 속성명 String AttrValue = attr.getnodevalue(); // 속성값 mresult.settext(" 루트요소이름 :" + rootname + "\n 자식요소이름 :" + childname + "\n 자식요소내용 :" + childvalue + "\n 자식요소속성명 :" + AttrName + "\n 자식요소속성값 :" + AttrValue); catch (Exception e){ mresult.settext(" 오류 "); // raw 디렉터리내의 student.xml 파일을읽어와스트림에저장 Resources res = getresources(); InputStream istream = res.openrawresource(r.raw.student); // parse 메소드로스트림을파싱하여 Document 객체를얻음 Document doc = builder.parse(istream);
MainActivity 코드 ( 두번째예제 ) import android.os.bundle; import android.os.handler; import android.os.message; import android.app.activity; import android.view.*; import android.widget.*; import javax.xml.parsers.*; import org.w3c.dom.*; import java.io.inputstream; import java.net.malformedurlexception; import java.net.url; import java.util.arraylist; public class MainActivity extends Activity { ArrayList<String> Headline = new ArrayList<String>(); ArrayAdapter<String> Adapter; ListView list; Handler mhandler = new Handler(){ public void handlemessage(message msg){ if(msg.what == 0){ Adapter = new ArrayAdapter<String>(MainActivity.this, android.r.layout.simple_list_item_1, Headline); list.setadapter(adapter); ; // url 을통해웹문서를읽어옴 public void gettext(){ try{ //////// xml 문서를파싱하기위한준비 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newdocumentbuilder(); protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); Button btn = (Button)findViewById(R.id.btn); list = (ListView)findViewById(R.id.list); btn.setonclicklistener(monclick); View.OnClickListener monclick = new View.OnClickListener() { @Override public void onclick(view v) { DataLoading thread = new DataLoading(); thread.start(); ; // 데이터로딩쓰레드 class DataLoading extends Thread { public void run(){ try{ gettext(); mhandler.sendemptymessage(0);// 데이터를얻어오면핸들러에게신호전달 catch(exception e){ e.printstacktrace(); //////// xml 웹문서를 Document 객체로만드는과정 String url= "http://rss.hankyung.com/new/news_intl.xml"; // 주소 URL nurl = new URL(url); InputStream xml = nurl.openstream(); Document doc = builder.parse(xml); //////// 엘리먼트접근 Element root = doc.getdocumentelement(); // 루트엘리먼트 // item이란이름을가진모든요소를찾는다. NodeList items = root.getelementsbytagname("item"); for(int i=0;i<items.getlength();i++){ // 찾은갯수만큼루프 Node item = items.item(i); // 하나의 item요소접근 // item요소의두번째자식요소 title 접근 ( 첫번째자식은텍스트노드 ) Node title = item.getfirstchild().getnextsibling(); Node value = title.getfirstchild(); // title 요소의내용접근 Headline.add(value.getNodeValue()); // 내용을 Arraylist에삽입 catch (MalformedURLException e) { e.printstacktrace(); catch(exception e){ e.printstacktrace();
3. SAX Parser
SAX Parser SAX Parsing 의장점 메모리를차지하는공간이적음 XML 데이터를모두메모리에적재하지않고라인 ( 시작태그 - 종료태그 ) 단위로마킹 대용량 XML 을 Parsing 해도속도가빠름 1 라인 2 라인
SAX Parser SAX Parsing 의단점 지나간엘리먼트를읽어오기위해서는처음부터다시읽어야함 특정엘리먼트에대해서어떻게동작할지사용자가직접정의
SAX Parser SAX API 프로그래밍을하려면? 1 세개의패키지를 import - [org.xml.sax], [ogr.xml.sax.helpers], [javax.xml.parsers] 2 이벤트핸들러클래스를설계하여이벤트핸들러를등록 3 파서객체를생성 4 이벤트핸들러로이벤트객체생성 5 파서객체에이벤트객체를적용시켜서 XML문서파싱
SAX Parser 1 이벤트핸들러클래스설계 DefaultHandler 클래스로부터상속받아이벤트핸들러클래스를설계 class MyHandler extends DefaultHandler { public void startdocument(){ // 문서의시작 public void startelement(){ // 요소의시작 public void endelement( ){ // 요소의끝 public void enddocument( ){ // 문서의종료
SAX Parser 2 파서객체생성 추상클래스 SAXParserFactory 의 newsaxparser 메소드를사용하여생성 SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newsaxparser();
SAX Parser 3 이벤트객체생성 앞서 1 에서설계한 MyHandler 클래스로객체생성 MyHandler myh = new MyHandler();
SAX Parser 4 요소추출 메소드에대한이해 public void startelement(string nsuri, String name, String qname, Attributes atts){ //startelement() 는 XML태그를만나면호출 //name : XML네임스페이스의접두사를제외한태그이름 //qname : XML네임스페이스의접두사를포함한태그이름 //atts : 태그에선언한속성 public void characters(char ch[], int start, int length){ //charcters() 는 XML 의태그가아닌데이터를알려주는메소드 // 데이터내용은 ch 의 start 인덱스에서 length 만큼의문자에해당
SAX Parser 5 속성의이름과값알아내기 startelement() 메소드는속성에대한정보를 Attributes 를통해알아냄 Attributes 의 getlength() 메소드는속성의개수 Attributes 의 getqname() 메소드는속성의이름 Attributes 의 getvalue() 메소드는속성의값
SAX Parser 간단한예제 1( 내부 XML 파싱 ) 버튼을누르면다음의 XML 을파싱하는프로그램
SAX Parser XML 생성 1 프로젝트생성후 [res] 디렉터리에 [raw] 폴더생성 2 [raw] 폴더에 [test.xml] 생성 3 다음과같이 XML 데이터작성
SAX Parser Activity_main.xml 1 [layout]-[activity_main.xml] 에서 Button 생성 2 동일한방법으로 TextView 생성 Button TextView
SAX Parser SAXHandler.java 1 [src]-[packge]-[saxhandler.java] 를생성하고 DefaultHandler 를상속 2 컨텐트를저장하는 str 객체, 속성을저장하는 attr 객체, element 의시작과끝을알리는 isappend 변수선언 3 startelement() 는시작태그를만나면실행되는메소드고 sedan 이라는태그를만나면 isappend 에 true 값을주어라인시작을알리고속성명과속성값을 attr 에저장 (Log.i() 는이클립스의 LogCat 에로그정보를보기위해사용, 생략가능 )
SAX Parser SAXHandler.java 4 컨텐트를저장하고컨텐트와속성을출력하는 characters() 메소드 5 endelement() 는종료태그를만나면실행되는메소드고엘리먼트 isappend 를 false 값을줌으로써라인의끝을알림
SAX Parser SAXHandler.java 5 stardocument(), enddocument() XML 문서의시작과끝을알리는메소드이고특별한오버라이딩은하지않고호출되는지확인하기위해 Log.i() 만사용
SAX Parser MainActivity.java 1 [src]-[packge]-[mainactivity.java] 에서 Activity 를상속받은 MainActivity 에사용할 TextView 와 Button 객체생성 2 oncreate() 메소드에사용될 TextView 와 Button ID 를불러옴
SAX Parser MainActivity.java 3 Button parse는버튼이눌리면파스를해야하므로이벤트추가 4 앞서만들어놓은 [raw]-[test.xml] 을가져오기위한 Resource클래스, XML을입력하기위한 InputStream클래스선언 5 파서객체를선언하고앞서생성한이벤트핸들러로파싱
SAX Parser 실행결과
SAX Parser 간단한예제 2( 외부 XML 파싱 ) 버튼을누르면다음의 XML 을파싱하는프로그램 (http://www.xmlfiles.com/examples/cd_catalog.xml) CATALOG CD TITLE ARTIST PRICE YEAR CD TITLE ARTIST PRICE YEAR
SAX Parser AndroidManifest.xml 1 컴퓨터내에존재하는 XML 과달리웹페이지에존재하는 XML 을파싱하기위해서퍼미션설정 2 AndroidManifest.xml 코드상에다음구문을추가 또는 [permissions] 탭에서설정가능
SAX Parser 3 4 2 1 5
SAX Parser Activity_main.xml 1 XML 데이터가많으므로 TextView 에서내용이잘리지않도록 ScrollView 사용 Button TextView ScrollView
SAX Parser SAXHandler.java 1 [src]-[packge]-[saxhandler.java] 를생성하고 DefaultHandler 를상속받아 SAXHandler 의메소드를오버라이딩 2 컨텐트를저장하는 str 객체, 총엘리먼트의개수를알리는변수 count 선언 3 컨텐트를저장하고컨텐트와속성을출력하는 characters() 메소드
SAX Parser SAXHandler.java 4 startelement() 는시작태그를만나면실행되는메소드고각태그의컨텐트앞에태그명을붙여주기위해조건문을사용
SAX Parser SAXHandler.java 5 endelement() 는종료태그를만나면실행되는메소드이고 CD 태그를이용하여구분선을넣어주고 CD 개수를카운트하는변수 1 증가 6 stardocument(), enddocument() XML 문서의시작과끝을알리는메소드이고 XML 문서끝을만나면총 CD 개수를출력
SAX Parser MainActivity.java 1 [src]-[packge]-[mainactivity.java] 에서 Activity 를상속받은 MainActivity 에사용할 ScrollView, TextView 와 Button 객체생성 2 oncreate() 메소드에사용될 ScrollView, TextView, Button ID 를불러옴
SAX Parser MainActivity.java 3 4 Button parse는버튼이눌리면파스를해야하므로이벤트추가 XML을읽어오는 XMLReader 객체를생성하고 URL객체를통해 XML 이있는 URL를받아파싱
SAX Parser android.os.networkonmainthreadexception 원인 안드로이드 3.0 버전이후부터발생되는오류 해결책 MainThread 에서는 UI 작업만담당하는역할 ANR(Application Not Responding) 을방지 강제로사용이가능하게함 MainActivity.java에 oncreate() 내부 setcontentview() 아래에다음의코드를추가 AndroidManifest.xml 의버전을 9 로변경
SAX Parser 실행결과
예제 1 소스코드 MainActivity.java package com.example.pharsingsax; import java.io.inputstream; import javax.xml.parsers.saxparser; import javax.xml.parsers.saxparserfactory; import android.app.activity; import android.content.res.resources; import android.os.bundle; import android.view.view; import android.view.view.onclicklistener; import android.widget.button; import android.widget.textview; public class MainActivity extends Activity { static TextView result; Button parse; @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); result = (TextView) findviewbyid(r.id.result); findviewbyid(r.id.parse).setonclicklistener(new OnClickListener(){ @Override public void onclick(view v) { result.settext(""); Resources res = getresources(); InputStream is = res.openrawresource(r.raw.test); try{ SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newsaxparser(); SAXHandler handler = new SAXHandler(); parser.parse(is, handler); catch (Exception e){ e.printstacktrace(); ); SAXHandler.java package com.example.pharsingsax; import org.xml.sax.attributes; import org.xml.sax.saxexception; import org.xml.sax.helpers.defaulthandler; import android.util.log; class SAXHandler extends DefaultHandler { StringBuffer str = new StringBuffer(); StringBuffer attr = new StringBuffer(); boolean isappend = false; public void characters(char[] ch, int start, int length) throws SAXException{ String temp = new String(ch, start, length); if(isappend==true&&temp.trim().length()!=0){ str.append(temp); MainActivity.result.append("\n"+str+"\n----------------------------\n"); MainActivity.result.append(attr); str.delete(0, str.length()); attr.delete(0, attr.length()); public void startelement(string uri, String localname, String qname, Attributes attributes){ if(qname.equals("sedan")){ isappend = true; for(int index = 0; index < attributes.getlength(); index++){ attr.append(attributes.getqname(index)+" : " + attributes.getvalue(index)+"\n"); Log.i("sax", "startelement()"); public void endelement(string uri, String localname, String qname) throws SAXException { IsAppend = false; Log.i("sax", "endelement()"); public void startdocument() throws SAXException{ Log.i("sax", "startdocument()"); public void enddocument() throws SAXException{ Log.i("sax", "enddocument()");
예제 1 소스코드 Activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/parse" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="parse" /> test.xml <?xml version="1.0" encoding="utf-8"?> <car> <sedan type=" 대형 " cc="3000cc" price="4000"> Granduer </sedan> <sedan type=" 중형 " cc="2000cc" price="3000"> Sonata </sedan> </car> <TextView android:id="@+id/result" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="left top" android:textsize="10pt" /> </LinearLayout>
예제 2 소스코드 MainActivity.java package com.example.pharsingsax; import java.net.url; import javax.xml.parsers.saxparser; import javax.xml.parsers.saxparserfactory; import org.xml.sax.inputsource; import org.xml.sax.xmlreader; import android.app.activity; import android.os.bundle; import android.os.strictmode; import android.view.view; import android.view.view.onclicklistener; import android.widget.button; import android.widget.scrollview; import android.widget.textview; @Override public void onclick(view v) { result.settext(""); try{ SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newsaxparser(); SAXHandler handler = new SAXHandler(); XMLReader xmlr = parser.getxmlreader(); URL url = new URL("http://www.xmlfiles.com/examples/cd_catalog.xml"); xmlr.setcontenthandler(handler); xmlr.parse(new InputSource(url.openStream())); catch (Exception e){ e.printstacktrace(); ); public class MainActivity extends Activity { static TextView result; Button parse; ScrollView mscrollview; @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(). detectdiskreads().detectdiskwrites().detectnetwork().penaltylog().build()); mscrollview =(ScrollView) findviewbyid(r.id.mscrollview); result = (TextView) findviewbyid(r.id.result); findviewbyid(r.id.parse).setonclicklistener(new OnClickListener(){
예제 2 소스코드 SAXHandler.java package com.example.pharsingsax; import org.xml.sax.attributes; import org.xml.sax.saxexception; import org.xml.sax.helpers.defaulthandler; import android.util.log; class SAXHandler extends DefaultHandler { StringBuffer str = new StringBuffer(); int count = 0; public void characters(char[] ch, int start, int length) throws SAXException{ String temp = new String(ch, start, length); if(temp.trim().length()!=0){ str.append(temp); MainActivity.result.append(str); str.delete(0, str.length()); public void startelement(string uri, String localname, String qname, Attributes attributes){ Log.i("sax", "startelement()"); if(localname.equals("title")){ MainActivity.result.append("\n TITLE : "); else if(localname.equals("artist")){ MainActivity.result.append("\n ARTIST : "); else if(localname.equals("country")){ MainActivity.result.append("\n COUNTRY : "); else if(localname.equals("price")){ MainActivity.result.append("\n PRICE : "); else if(localname.equals("year")){ MainActivity.result.append("\n YEAR : "); public void endelement(string uri, String localname, String qname) throws SAXException { if(localname.equals("cd")){ count++; MainActivity.result.append("\n----------------------------\n"); public void startdocument() throws SAXException{ public void enddocument() throws SAXException{ MainActivity.result.append("TOTAL :" + count +"\n-------------------------- --\n");
예제 2 소스코드 Activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/parse" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="parse" /> <ScrollView android:id="@+id/mscrollview" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/result" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="left top" android:textsize="10pt" /> </ScrollView> </LinearLayout> AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.pharsingsax" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="9" android:targetsdkversion="18" /> <uses-permission android:name="android.permission.internet"/> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name="com.example.pharsingsax.mainactivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> </application> </manifest>
4. XML Pull Parser
XML Pull Parser XML Pull Parser 특징 1. 전체동작방식은 SAX와비슷 2. SAX와달리이벤트핸들러를작성하지않아도되므로간편 3. 문서의일부분만작업해야할경우엔 SAX보다빠르고단순하게처리가능
Pull Parser 코드작성방법 1. 빌더생성후파서객체생성 newinstance() 를통해빌더팩토리생성후 newpullparser() 메소드를통해파서객체를얻는다. 2. 분석하고싶은 xml 파일을설정 XmlPullParser 클래스의 setinput(inputstream, String) 을통해분석할 xml 과인코딩방식을설정
Pull Parser 코드작성방법 3. 문서를순차적으로읽으면서이벤트를진행 현재이벤트를분석하고 next() 메소드로다음이벤트로이동시킨다.
XMLPullParser 분석진행방법 ( 속성 ) 속성 의미 START_DOCUMENT START_TAG TEXT END_TAG END_DOCUMENT XML 파일의시작에도달했을때반환 요소의시작태그를만났을때반환 요소의텍스트를만났을때반환 (<tag>text</tag> 에서 TEXT) 요소의종료태그를만났을때반환 (</tag>) XML 파일의끝에도달했을때반환 geteventtype() 으로현재속성을가져오고 next() 로다음속성으로이동
XmlPullParser 형식을 이용한간단한예제
예제 1 이클립스에서안드로이드프로젝트생성후 res raw 디렉터리에 test.xml 생성
예제 1 test.xml 파일에다음과같이입력
예제 1 LinearLayout 내부에 Button 과 TextView 를추가
예제 1 MainActivity 클래스의상속을 Activity 로고치고 TextView 와 Button 객체를생성후 oncreate() 메소드에사용될 TextView 와 Button 을불러옴
예제 1 버튼이클릭되었을때이벤트를발생시키는 onclick() 선언 Resouces 클래스와 InputStream 클래스를통해 xml 파일을읽어옴 PullPaser 인스턴스를생성하여파서객체를얻고 setinput() 메소드를이용하여 xml 을저장
예제 1 1 2 태그가맞게들어왔는지체크하기위한 boolean데이터타입을선언하고 tag를저장하기위한 tag변수와문자열을저장하고출력해주기위해 StringBuffer클래스를사용합니다. 이벤트타입을얻기위해 geteventtype메소드로저장을하고 SAX의이벤트핸들러대신루프를써서 end태그가아니면루프를돌면서파싱을하게한다.
예제 1 START_TAG 를만나면 getname() 메소드를이용하여현재태그의이름을저장하고그태그가 student 을경우태그가들어왔으므로 true 로설정하고 StingBuffer 의변수 attr.append() 를이용해속성의이름과속성의내용을저장한다.
예제 1 TEXT 태그를만났을경우태그의내용과 StringBuffer 로추가시킨문자열을 TextView 에출력시켜줍니다. 그리고 next() 메소드를통해다음태그로이벤트를이동시킨다.
예제 1 실행결과 버튼클릭
XmlPullParser 를이용한 간단한웹문서파싱
예제 2 기상청 RSS http://www.kma.go.kr/weather/lifenindustry/sevice_rss.jsp 파싱할동네주소선택후 RSS 버튼클릭
예제 2 필요한태그만지정하여파싱
예제 2 Activity_main.xml
예제 2 AndroidManifest.xml 2 3 4 1
예제 2 AndroidManifest.xml 5
예제 2 MainActivity 클래스에서 TextView, Button 의객체와내용이잘리지않기위한 ScrollView 객체를선언하고 String 형으로외부 xml 사이트를저장하고 URL 클래스를선언후 oncreate() 메소드에서사용될각각의객체들을불러온다.
예제 2 1 2 onclick() 은버튼이클릭되었을때이벤트를발생시키는메소드으로그내부에는 URL클래스를객체선언하여 uri에저장된사이트를접속하여 xml데이터를읽어 inputstream에저장시킨다. PullParser인스턴스를생성하여파서객체를얻고 setinput() 메소드를이용하여 xml을저장한다.
예제 2 루프문을이용하여 EventType 이 END_DOCUMENT 를만날때까지계속실행시킨다. START_TAG 를만나면 getname() 을이용하여현재태그명을저장하고해당태그명이일치할경우 TextView 에해당출력물을출력시킨다.
예제 2 TEXT 와 END_TAG 도마찬가지로현재해당태그명의조건에있을경우그에따른결과를출력해주면된다. 그리고 next() 메소드를통해다음태그로이벤트를이동시킨다.
예제 2 실행결과 버튼클릭
예제 1 소스코드 MainActivity.java package com.example.xmlpullparser; import java.io.inputstream; import org.xmlpull.v1.xmlpullparser; import org.xmlpull.v1.xmlpullparserexception; import org.xmlpull.v1.xmlpullparserfactory; import android.support.v7.app.actionbaractivity; import android.support.v7.app.actionbar; import android.support.v4.app.fragment; import android.app.activity; import android.content.res.resources; import android.os.bundle; import android.view.layoutinflater; import android.view.menu; import android.view.menuitem; import android.view.view; import android.view.view.onclicklistener; import android.view.viewgroup; import android.widget.button; import android.widget.textview; import android.os.build; public class MainActivity extends Activity { TextView result; Button parse; @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.fragment_main); result= (TextView)findViewById(R.id.result); findviewbyid(r.id.parse).setonclicklistener(new OnClickListener() { @Override public void onclick(view v) { result.settext(""); Resources res = getresources(); InputStream is = res.openrawresource(r.raw.test); try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newpullparser(); parser.setinput(is,null); boolean bool = false; String tag; StringBuffer attr = new StringBuffer(); int EventType = parser.geteventtype(); while(eventtype!= XmlPullParser.END_DOCUMENT){ switch(eventtype){ case XmlPullParser.START_TAG: tag = parser.getname(); if(tag.equals("student")){ bool=true; int index; for(index=0;index<parser.getattributecount();index++){ attr.append(parser.getattributename(index) +" : " +parser.getattributevalue(index) +"\n"); break; case XmlPullParser.TEXT: if(bool==true){ result.append(parser.gettext()); result.append("\n---------------------------\n"); result.append(attr); attr.delete(0, attr.length()); bool=false; break; //end of switch EventType = parser.next(); catch (Exception e) { e.printstacktrace();
예제 1 소스코드 Activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/parse" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text=" 버튼클릭 "/> <TextView android:id="@+id/result" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="left top" android:textsize="10pt" /> </LinearLayout> AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.xmlpullparser" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="8" android:targetsdkversion="17" /> <uses-permission android:name="android.permission.internet"/> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name="com.example.xmlpullparser.mainactivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> </application> </manifest>
예제 2 소스코드 MainActivity.java package com.example.weather; import java.io.inputstream; import java.net.url; import org.xmlpull.v1.xmlpullparser; import org.xmlpull.v1.xmlpullparserfactory; import android.support.v7.app.actionbaractivity; import android.support.v7.app.actionbar; import android.support.v4.app.fragment; import android.app.activity; import android.os.bundle; import android.os.strictmode; import android.view.layoutinflater; import android.view.menu; import android.view.menuitem; import android.view.view; import android.view.viewgroup; import android.view.view.onclicklistener; import android.widget.button; import android.widget.scrollview; import android.widget.textview; import android.os.build; public class MainActivity extends Activity { TextView result; Button parse; ScrollView mscrollview; String uri = "http://www.kma.go.kr/wid/querydfsrss.jsp?zone=4719069000.xml"; URL newsurl; @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.fragment_main); mscrollview = (ScrollView)findViewById(R.id.mScrollView); result = (TextView) findviewbyid(r.id.result); { findviewbyid(r.id.parse).setonclicklistener(new OnClickListener() @Override public void onclick(view v) { result.settext(""); try { newsurl = new URL(uri); InputStream in = newsurl.openstream(); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newpullparser(); parser.setinput(in, "utf-8"); String tag = ""; int EventType = parser.geteventtype(); while (EventType!= XmlPullParser.END_DOCUMENT) { switch(eventtype){ case XmlPullParser.START_TAG: tag = parser.getname(); if(tag.equals("hour")){ result.append(" 시간 : "); else if(tag.equals("temp")){ result.append(" 기온 :"); else if(tag.equals("wfkor")){ result.append(" 하늘 : "); else if(tag.equals("pop")){ result.append(" 강수확률 : "); break; case XmlPullParser.TEXT: if(tag.equals("hour")){ result.append(parser.gettext()); else if(tag.equals("temp")){ result.append(parser.gettext()); else if(tag.equals("wfkor")){ result.append(parser.gettext()); else if(tag.equals("pop")){ result.append(parser.gettext()); else if(tag.equals("pubdate")){ result.append(parser.gettext()); break; case XmlPullParser.END_TAG: tag = parser.getname(); if(tag.equals("data")){ result.append("======================\n");
예제 2 소스코드 Activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/parse" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text=" 구미시양포동날씨보기 "/> <ScrollView android:id="@+id/mscrollview" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/result" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="left top" android:textsize="10pt" /> </ScrollView> </LinearLayout> AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.weather" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="9" android:targetsdkversion="17" /> <uses-permission android:name="android.permission.internet"/> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name="com.example.weather.mainactivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> </application> </manifest>