print("와챠의 개발 기록장")
[안드로이드] 안드로이드 XML 데이터 파싱 본문
반응형

안드로이드에서 XML로 데이터 파싱하기
1) id 선언/연결 쉽게 하려고
glable에 id 'kotlin-android-extensions' 추가
2) AndroidManifest.xml에서
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 추가
application 안에
android:usesCleartextTraffic="true" 추가
AndroidManifest.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="com.example.myopenhospital"> | |
<uses-permission android:name="android.permission.INTERNET" /> | |
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | |
<application | |
android:allowBackup="true" | |
android:icon="@mipmap/ic_launcher" | |
android:usesCleartextTraffic="true" | |
android:label="@string/app_name" | |
android:roundIcon="@mipmap/ic_launcher_round" | |
android:supportsRtl="true" | |
android:theme="@style/Theme.MyOpenHospital"> | |
<activity android:name=".MainActivity"> | |
<intent-filter> | |
<action android:name="android.intent.action.MAIN" /> | |
<category android:name="android.intent.category.LAUNCHER" /> | |
</intent-filter> | |
</activity> | |
</application> | |
</manifest> |
hospital.xml

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:orientation="vertical" android:layout_width="match_parent" | |
android:layout_height="wrap_content"> | |
<TextView | |
android:id="@+id/tvHospitalName" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="기관명" | |
android:textColor="#0000ff" | |
android:textSize="30dp"/> | |
<TextView | |
android:id="@+id/tvAreaName" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="시도명"/> | |
<TextView | |
android:id="@+id/tvPhoneNumber" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="전화번호"/> | |
</LinearLayout> |
activity_main.xml

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
xmlns:tools="http://schemas.android.com/tools" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
tools:context=".MainActivity" | |
android:orientation="vertical"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:orientation="horizontal" | |
android:layout_weight="1"> | |
<RadioGroup | |
android:id="@+id/rGroup" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_weight="8"> | |
<RadioButton | |
android:id="@+id/A0" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="국민 안심 병원"/> | |
<RadioButton | |
android:id="@+id/A97" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="코로나 검사 실시 기관"/> | |
<RadioButton | |
android:id="@+id/A99" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="코로나 선별 진료소 운영 기관"/> | |
</RadioGroup> | |
<Button | |
android:id="@+id/btnSeatch" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_weight="2" | |
android:text="병원 검색"/> | |
</LinearLayout> | |
<androidx.recyclerview.widget.RecyclerView | |
android:id="@+id/listView" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:layout_weight="9"/> | |
</LinearLayout> |
Hospital.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.myopenhospital | |
// 데이터 클래스 | |
data class Hospital ( | |
val hospitalName : String, | |
val areaName : String, | |
val phoneNumber : String | |
) |
HospitalAdapter.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.myopenhospital | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import androidx.recyclerview.widget.RecyclerView | |
import kotlinx.android.synthetic.main.hospital.view.* | |
class HospitalAdapter (var items : ArrayList<Hospital>) : RecyclerView.Adapter<HospitalAdapter.ViewHolder>() { | |
// 뷰 홀더 만들어서 반환, 뷰릐 레이아웃은 hospital.xml | |
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HospitalAdapter.ViewHolder { | |
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.hospital, parent, false) | |
return ViewHolder(itemView) | |
} | |
// 전달받은 위치의 아이템 연결 | |
override fun onBindViewHolder(holder: HospitalAdapter.ViewHolder, position: Int) { | |
val item = items[position] | |
holder.setItem(item) | |
} | |
// 아이템 갯수 리턴 | |
override fun getItemCount() = items.count() | |
// 뷰 홀더 설정 | |
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) { | |
fun setItem(item : Hospital) { | |
itemView.tvHospitalName.text = item.hospitalName | |
itemView.tvAreaName.text = item.areaName | |
itemView.tvPhoneNumber.text = item.phoneNumber | |
} | |
} | |
} |
MainActivity.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.myopenhospital | |
import android.os.AsyncTask | |
import androidx.appcompat.app.AppCompatActivity | |
import android.os.Bundle | |
import android.widget.Toast | |
import androidx.recyclerview.widget.LinearLayoutManager | |
import kotlinx.android.synthetic.main.activity_main.* | |
import org.xmlpull.v1.XmlPullParser | |
import org.xmlpull.v1.XmlPullParserFactory | |
import java.io.BufferedReader | |
import java.io.InputStreamReader | |
import java.io.StringReader | |
import java.net.URL | |
class MainActivity : AppCompatActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
// 버튼 클릭 시 병원 검색 | |
btnSeatch.setOnClickListener { | |
// 리사이클러 뷰 매니저 설정정 | |
listView.layoutManager = LinearLayoutManager(this) | |
val serviceUrl = "http://apis.data.go.kr/B551182/pubReliefHospService/getpubReliefHospList" // End Point | |
val serviceKey = "인증키" | |
// pageNo=1&numOfRows=10 은 그대로 | |
var spclAdmTyCd = "" | |
when(rGroup.checkedRadioButtonId) { | |
R.id.A0 -> spclAdmTyCd = "A0" | |
R.id.A97 -> spclAdmTyCd = "97" | |
R.id.A99 -> spclAdmTyCd = "99" | |
else -> Toast.makeText(applicationContext, "병원 코드를 먼저 선택하세요.", Toast.LENGTH_SHORT).show() | |
} | |
// 이 url 주소 가지고 데이터 획득하기 | |
val requstUrl = serviceUrl + "?serviceKey=" + serviceKey + | |
"&pageNo=1&numOfRows=10&spclAdmTyCd=" + spclAdmTyCd | |
fetchXML(requstUrl) | |
} | |
} | |
fun fetchXML(url : String) { | |
lateinit var page : String // url 주소 통해 전달받은 내용 저장할 변수 | |
// xml 데이터 가져와서 파싱하기 | |
// 외부에서 데이터 가져올 때 화면 계속 동작하도록 AsyncTask 이용 | |
class getDangerGrade : AsyncTask<Void, Void, Void>() { | |
// url 이용해서 xml 읽어오기 | |
override fun doInBackground(vararg p0: Void?): Void? { | |
// 데이터 스트림 형태로 가져오기 | |
val stream = URL(url).openStream() | |
val bufReader = BufferedReader(InputStreamReader(stream, "UTF-8")) | |
// 한줄씩 읽어서 스트링 형태로 바꾼 후 page에 저장 | |
page = "" | |
var line = bufReader.readLine() | |
while (line != null) { | |
page += line | |
line = bufReader.readLine() | |
} | |
return null | |
} | |
// 읽어온 xml 파싱하기 | |
override fun onPostExecute(result: Void?) { | |
super.onPostExecute(result) | |
var itemList : ArrayList<Hospital> = arrayListOf() // 저장될 데이터 배열 | |
var bSet1 = false // 시도 태그 | |
var bSet2 = false // 시군구 태그 | |
var bSet3 = false // 기관명 태그 | |
var bSet4 = false // 전화번호 태그 | |
lateinit var sidoNm : String // 시도명 | |
lateinit var sgguNm : String // 시군구명 | |
lateinit var yadmNm : String // 기관명 | |
lateinit var telno : String // 전화번호 | |
var factory = XmlPullParserFactory.newInstance() // 파서 생성 | |
factory.setNamespaceAware(true) // 파서 설정 | |
var xpp = factory.newPullParser() // XML 파서 | |
// 파싱하기 | |
xpp.setInput(StringReader(page)) | |
// 파싱 진행 | |
var eventType = xpp.eventType | |
while (eventType != XmlPullParser.END_DOCUMENT) { | |
if (eventType == XmlPullParser.START_DOCUMENT) {} | |
else if (eventType == XmlPullParser.START_TAG) { | |
var tagName = xpp.name | |
if (tagName.equals("sidoNm")) bSet1 = true | |
else if (tagName.equals("sgguNm")) bSet2 = true | |
else if (tagName.equals("yadmNm")) bSet3 = true | |
else if (tagName.equals("telno")) bSet4 = true | |
} | |
if (eventType == XmlPullParser.TEXT) { | |
if (bSet1) { // 시도명 | |
sidoNm = xpp.text | |
bSet1 = false | |
} | |
else if (bSet2) { // 시군구명 | |
sgguNm = xpp.text | |
bSet2 = false | |
} | |
else if (bSet3) { // 기관명 | |
yadmNm = xpp.text | |
bSet3 = false | |
// 기관명까지 다 읽으면 하나의 데이터 다 읽은 것임 | |
var item = Hospital(yadmNm, sidoNm + " " + sgguNm, telno) | |
itemList.add(item) | |
} | |
else if (bSet4) { // 전화번호 | |
telno = xpp.text | |
bSet4 = false | |
} | |
} | |
if (eventType == XmlPullParser.END_TAG) {} | |
// itemList.add() | |
eventType = xpp.next() | |
} | |
// 리아시클러 뷰에 데이터 연결 | |
listView.adapter = HospitalAdapter(itemList) | |
} | |
} | |
getDangerGrade().execute() | |
} | |
} |
참고로 xml 이렇게 생김

반응형
'코딩 일기장 > Android(Kotlin)' 카테고리의 다른 글
[안드로이드] 웹 크롤링(이미지) (2) | 2021.05.14 |
---|---|
[안드로이드] 웹 크롤링 (0) | 2021.05.14 |
[안드로이드] 기상청 동네예보 API 활용하기 (7) | 2021.05.09 |
[안드로이드] 카카오 로그인(2) (0) | 2021.05.07 |
[안드로이드] 카카오 로그인 api(1) (0) | 2021.05.07 |