회기역 지하철 시간 타이머 앱 - 2 (xml parse)
https://data.seoul.go.kr/dataList/OA-12764/F/1/datasetView.do
열린데이터광장 메인
데이터분류,데이터검색,데이터활용
data.seoul.go.kr
여기서 API 인증키를 신청해서 받았고, 이제 서버통신만 하면되는줄 알았는데,,
여기서 제공하는 데이터가 xml 형식이더라...
json이면 편할텐데........
flutter로 xml 파싱하는 방법에 대해서 공부했다.
https://www.youtube.com/watch?v=J9b13J8-osM&list=PLgRxBCVPaZ_269IOayEny-_aq0LUQ2fGl&index=2
자료는 이 영상을 참고했다.
우선 데이터 형식을 긁어서 어떤 형식인지 확인해야한다.
<realtimeStationArrival>
<RESULT>
<code>INFO-000</code>
<developerMessage/>
<link/>
<message>정상 처리되었습니다.</message>
<status>200</status>
<total>13</total>
</RESULT>
<row>
<rowNum>1</rowNum>
<selectedCount>3</selectedCount>
<totalCount>13</totalCount>
<subwayId>1001</subwayId>
<updnLine>상행</updnLine>
<trainLineNm>소요산행 - 외대앞방면</trainLineNm>
<statnFid>1001000124</statnFid>
<statnTid>1001000122</statnTid>
<statnId>1001000123</statnId>
<statnNm>회기</statnNm>
<ordkey>01000소요산0</ordkey>
<subwayList>1001,1063</subwayList>
<statnList>1001000123,1063075118</statnList>
<barvlDt>0</barvlDt>
<btrainNo>0112</btrainNo>
<bstatnId>190</bstatnId>
<bstatnNm>소요산</bstatnNm>
<recptnDt>2023-05-03 15:47:33</recptnDt>
<arvlMsg2>회기 도착</arvlMsg2>
<arvlMsg3>회기</arvlMsg3>
<arvlCd>1</arvlCd>
</row>
<row>
<rowNum>2</rowNum>
<selectedCount>3</selectedCount>
<totalCount>13</totalCount>
<subwayId>1063</subwayId>
<updnLine>상행</updnLine>
<trainLineNm>문산행 - 청량리방면</trainLineNm>
<statnFid>1063075119</statnFid>
<statnTid>1063075117</statnTid>
<statnId>1063075118</statnId>
<statnNm>회기</statnNm>
<ordkey>01002문산0</ordkey>
<subwayList>1001,1063,1067</subwayList>
<statnList>1001000123,1063075118</statnList>
<barvlDt>0</barvlDt>
<btrainNo>5092</btrainNo>
<bstatnId>234</bstatnId>
<bstatnNm>문산</bstatnNm>
<recptnDt>2023-05-03 15:47:38</recptnDt>
<arvlMsg2>[2]번째 전역 (상봉)</arvlMsg2>
<arvlMsg3>상봉</arvlMsg3>
<arvlCd>99</arvlCd>
</row>
<row>
<rowNum>3</rowNum>
<selectedCount>3</selectedCount>
<totalCount>13</totalCount>
<subwayId>1067</subwayId>
<updnLine>상행</updnLine>
<trainLineNm>청량리행 - 청량리방면</trainLineNm>
<statnFid>1067080118</statnFid>
<statnTid>1067080116</statnTid>
<statnId>1067080117</statnId>
<statnNm>회기</statnNm>
<ordkey>01010청량리0</ordkey>
<subwayList>1001,1063,1067</subwayList>
<statnList>1001000123,1063075118,1067080117</statnList>
<barvlDt>0</barvlDt>
<btrainNo>8060</btrainNo>
<bstatnId>166</bstatnId>
<bstatnNm>청량리</bstatnNm>
<recptnDt>2023-05-03 15:48:27</recptnDt>
<arvlMsg2>[10]번째 전역 (평내호평)</arvlMsg2>
<arvlMsg3>평내호평</arvlMsg3>
<arvlCd>99</arvlCd>
</row>
</realtimeStationArrival>
길다..
쨌든 이 데이터를 처리를 해야되는데 row로 나뉘어져 있는걸 확인할 수 있다.
일단 이 데이터를 담을 class를 선언해준다
class Subway {
String? rowNum;
String? selectedCount;
String? totalCount;
String? subwayId;
String? updnLine;
String? trainLineNm;
String? statnFid;
String? statnTid;
String? statnId;
String? statnNm;
String? ordkey;
String? subwayList;
String? statnList;
String? barvlDt;
String? btrainNo;
String? bstatnId;
String? recptnDt;
String? arvlMsg2;
String? arvlMsg3;
String? arvlCd;
Subway({
this.rowNum,
this.selectedCount,
this.totalCount,
this.subwayId,
this.updnLine,
this.trainLineNm,
this.statnFid,
this.statnTid,
this.statnId,
this.statnNm,
this.ordkey,
this.subwayList,
this.statnList,
this.barvlDt,
this.btrainNo,
this.bstatnId,
this.recptnDt,
this.arvlMsg2,
this.arvlMsg3,
this.arvlCd});
}
항목이 너무많아도 어쩔 수 없다..
그 다음에는 깔끔한 코딩을 위해 xml을 집어넣는 클래스를 만들꺼다.
class PutElement{
static String searchResult(XmlElement xml, String key){
return xml.findAllElements(key).map((e) => e.text).isEmpty? "" :xml.findAllElements(key).map((e)=> e.text).first;
}
}
이 함수를 만든 다음에
위에서 만든 Subway class 를 수정해주면 된다.
class Subway {
String? rowNum;
String? selectedCount;
String? totalCount;
String? subwayId;
String? updnLine;
String? trainLineNm;
String? statnFid;
String? statnTid;
String? statnId;
String? statnNm;
String? ordkey;
String? subwayList;
String? statnList;
String? barvlDt;
String? btrainNo;
String? bstatnId;
String? recptnDt;
String? arvlMsg2;
String? arvlMsg3;
String? arvlCd;
Subway({
this.rowNum,
this.selectedCount,
this.totalCount,
this.subwayId,
this.updnLine,
this.trainLineNm,
this.statnFid,
this.statnTid,
this.statnId,
this.statnNm,
this.ordkey,
this.subwayList,
this.statnList,
this.barvlDt,
this.btrainNo,
this.bstatnId,
this.recptnDt,
this.arvlMsg2,
this.arvlMsg3,
this.arvlCd});
factory Subway.fromXml(XmlElement xml){
return Subway(
rowNum : PutElement.searchResult(xml, 'rowNum'),
selectedCount : PutElement.searchResult(xml, 'selectedCount'),
totalCount : PutElement.searchResult(xml, 'totalCount'),
subwayId : PutElement.searchResult(xml, 'subwayId'),
updnLine : PutElement.searchResult(xml, 'updnLine'),
trainLineNm : PutElement.searchResult(xml, 'trainLineNm'),
statnFid : PutElement.searchResult(xml, 'statnFid'),
statnTid : PutElement.searchResult(xml, 'statnTid'),
statnId : PutElement.searchResult(xml, 'statnId'),
statnNm : PutElement.searchResult(xml, 'statnNm'),
ordkey : PutElement.searchResult(xml, 'ordkey'),
subwayList : PutElement.searchResult(xml, 'subwayList'),
statnList : PutElement.searchResult(xml, 'statnList'),
barvlDt : PutElement.searchResult(xml, 'barvlDt'),
btrainNo : PutElement.searchResult(xml, 'btrainNo'),
bstatnId : PutElement.searchResult(xml, 'bstatnId'),
recptnDt : PutElement.searchResult(xml, 'recptnDt'),
arvlMsg2 : PutElement.searchResult(xml, 'arvlMsg2'),
arvlMsg3 : PutElement.searchResult(xml, 'arvlMsg3'),
arvlCd : PutElement.searchResult(xml, 'arvlCd'),
);
}
}
그러면 class에 xml 데이터를 parse하는 메소드는 만들었고 이제 직접적으로 main함수에서 parse를 해야한다.
임의로 데이터를 하나 긁어서 main에 넣어주고, 이를 넣어주는 main함수는
void main() {
final bookshelfXml = '''<realtimeStationArrival>
<RESULT>
<code>INFO-000</code>
<developerMessage/>
<link/>
<message>정상 처리되었습니다.</message>
<status>200</status>
<total>13</total>
</RESULT>
<row>
<rowNum>1</rowNum>
<selectedCount>3</selectedCount>
<totalCount>13</totalCount>
<subwayId>1001</subwayId>
<updnLine>상행</updnLine>
<trainLineNm>소요산행 - 외대앞방면</trainLineNm>
<statnFid>1001000124</statnFid>
<statnTid>1001000122</statnTid>
<statnId>1001000123</statnId>
<statnNm>회기</statnNm>
<ordkey>01000소요산0</ordkey>
<subwayList>1001,1063</subwayList>
<statnList>1001000123,1063075118</statnList>
<barvlDt>0</barvlDt>
<btrainNo>0112</btrainNo>
<bstatnId>190</bstatnId>
<bstatnNm>소요산</bstatnNm>
<recptnDt>2023-05-03 15:47:33</recptnDt>
<arvlMsg2>회기 도착</arvlMsg2>
<arvlMsg3>회기</arvlMsg3>
<arvlCd>1</arvlCd>
</row>
<row>
<rowNum>2</rowNum>
<selectedCount>3</selectedCount>
<totalCount>13</totalCount>
<subwayId>1063</subwayId>
<updnLine>상행</updnLine>
<trainLineNm>문산행 - 청량리방면</trainLineNm>
<statnFid>1063075119</statnFid>
<statnTid>1063075117</statnTid>
<statnId>1063075118</statnId>
<statnNm>회기</statnNm>
<ordkey>01002문산0</ordkey>
<subwayList>1001,1063,1067</subwayList>
<statnList>1001000123,1063075118</statnList>
<barvlDt>0</barvlDt>
<btrainNo>5092</btrainNo>
<bstatnId>234</bstatnId>
<bstatnNm>문산</bstatnNm>
<recptnDt>2023-05-03 15:47:38</recptnDt>
<arvlMsg2>[2]번째 전역 (상봉)</arvlMsg2>
<arvlMsg3>상봉</arvlMsg3>
<arvlCd>99</arvlCd>
</row>
<row>
<rowNum>3</rowNum>
<selectedCount>3</selectedCount>
<totalCount>13</totalCount>
<subwayId>1067</subwayId>
<updnLine>상행</updnLine>
<trainLineNm>청량리행 - 청량리방면</trainLineNm>
<statnFid>1067080118</statnFid>
<statnTid>1067080116</statnTid>
<statnId>1067080117</statnId>
<statnNm>회기</statnNm>
<ordkey>01010청량리0</ordkey>
<subwayList>1001,1063,1067</subwayList>
<statnList>1001000123,1063075118,1067080117</statnList>
<barvlDt>0</barvlDt>
<btrainNo>8060</btrainNo>
<bstatnId>166</bstatnId>
<bstatnNm>청량리</bstatnNm>
<recptnDt>2023-05-03 15:48:27</recptnDt>
<arvlMsg2>[10]번째 전역 (평내호평)</arvlMsg2>
<arvlMsg3>평내호평</arvlMsg3>
<arvlCd>99</arvlCd>
</row>
</realtimeStationArrival>''';
test('subway', () {
final document = XmlDocument.parse(bookshelfXml);
final items = document.findAllElements('row');
var subway = <Subway>[];
items.forEach((node) {
subway.add(Subway.fromXml(node));
});
print(subway.length);
subway.forEach((subway){
print('${subway.trainLineNm} : ${subway.recptnDt}');
});
});
}
이렇다
test안의 내용이 중요한데, items를 xml파일을 row로 나눠주고
이를 각각 subway class 변수에 넣어준다.
그리고 print를 해보면
Connecting to VM Service at http://127.0.0.1:56642/geY7XXBssi8=/ws
3
소요산행 - 외대앞방면 : 2023-05-03 15:47:33
문산행 - 청량리방면 : 2023-05-03 15:47:38
청량리행 - 청량리방면 : 2023-05-03 15:48:27
✓ subway
Exited
다음과 같이 결과가 나오는 것을 확인할 수 있다.
이제 parse는 끝났으니 http에서 데이터를 받아오는걸 해보면 된다.