java 메모

공공데이터(xml)를 이용한 html 테스트 #1

letsDoDev 2023. 9. 24. 21:33

- 응용할 xml 값 (너무 길어서 중략 함 전체 코드는 https://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=%s)

더보기

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>기상청 육상 중기예보</title>
<link>http://www.kma.go.kr/weather/forecast/mid-term_02.jsp</link>
<description>기상청 날씨 웹서비스</description>
<language>ko</language>
<generator>기상청</generator>
<pubDate>2023년 07월 25일 (화)요일 06:00</pubDate>
<item>
<author>기상청</author>
<category>육상중기예보</category>
<title>서울,경기도 육상 중기예보 - 2023년 07월 25일 (화)요일 06:00 발표</title>
<link>http://www.kma.go.kr/weather/forecast/mid-term_02.jsp</link>
<guid>http://www.kma.go.kr/weather/forecast/mid-term_02.jsp</guid>
<description>
<header>
<title>서울,경기도 육상중기예보</title>
<tm>202307250600</tm>
<wf>
<![CDATA[ ○ (강수) 28일(금) 오후에 소나기, 29일(토) 오후~30일(일) 오전은 비가 오는 곳이 있겠습니다. <br />○ (기온) 이번 예보기간 아침 기온은 23~26도로 평년(최저기온 22~24도)과 비슷하거나 조금 높겠고, 낮 기온은 28~33도로 평년(최고기온 29~33도)과 비슷하겠습니다.<br />○ (해상) 서해중부해상의 물결은 30일(일) 오후~31일(월) 오전, 8월 3일(목)은 1.5~2.5m, 그 밖의 날은 0.5~2.0m로 일겠습니다.<br />○ (주말 전망) 29일(토) 오후~30일(일) 오전은 비가 오겠습니다. 아침 기온은 23~25도, 낮 기온은 29~33도가 되겠습니다. <br /><br />* 이번 예보기간에는 제5호 태풍(독수리)의 이동경로와 북태평양고기압의 확장정도에 따라 강수구역이 변경될 가능성이 있으니, 앞으로 발표되는 예보를 참고하기 바랍니다. ]]>
</wf>
</header>
<body>
<location wl_ver="3">
<province>서울ㆍ인천ㆍ경기도</province>
<city>서울</city>
<data>
<mode>A02</mode>
<tmEf>2023-07-28 00:00</tmEf>
<wf>구름많음</wf>
<tmn>25</tmn>
<tmx>32</tmx>
<reliability />
<rnSt>30</rnSt>
</data>
<data>
<mode>A02</mode>
<tmEf>2023-07-28 12:00</tmEf>
<wf>구름많고 소나기</wf>
<tmn>25</tmn>
<tmx>32</tmx>
<reliability />
<rnSt>70</rnSt>
</data>
<data>
<mode>A02</mode>
<tmEf>2023-07-29 00:00</tmEf>
<wf>흐림</wf>
<tmn>25</tmn>
<tmx>31</tmx>
<reliability />
<rnSt>40</rnSt>
</data>
<data>
<mode>A02</mode>
<tmEf>2023-07-29 12:00</tmEf>
<wf>흐리고 비</wf>
<tmn>25</tmn>
<tmx>31</tmx>
<reliability />
<rnSt>60</rnSt>
</data>
<data>
<mode>A02</mode>
<tmEf>2023-07-30 00:00</tmEf>
<wf>흐리고 비</wf>
<tmn>25</tmn>
<tmx>31</tmx>
<reliability />
<rnSt>60</rnSt>
</data>
<data>
<mode>A02</mode>
<tmEf>2023-07-30 12:00</tmEf>
<wf>흐림</wf>
<tmn>25</tmn>
<tmx>31</tmx>
<reliability />
<rnSt>40</rnSt>
</data>
:

:
<data>
<mode>A01</mode>
<tmEf>2023-08-04 00:00</tmEf>
<wf>흐림</wf>
<tmn>25</tmn>
<tmx>31</tmx>
<reliability />
<rnSt>40</rnSt>
</data>
</location>
<location wl_ver="3">
<province>서울ㆍ인천ㆍ경기도</province>
<city>인천</city>
<data>
<mode>A02</mode>
<tmEf>2023-07-28 00:00</tmEf>
<wf>구름많음</wf>
<tmn>25</tmn>
<tmx>30</tmx>
<reliability />
<rnSt>30</rnSt>
</data>
<data>
<mode>A02</mode>
<tmEf>2023-07-28 12:00</tmEf>
<wf>구름많고 소나기</wf>
<tmn>25</tmn>
<tmx>30</tmx>
<reliability />
<rnSt>70</rnSt>
</data>
<data>
<mode>A02</mode>
<tmEf>2023-07-29 00:00</tmEf>
<wf>흐림</wf>
<tmn>25</tmn>
<tmx>29</tmx>
<reliability />
<rnSt>40</rnSt>
</data>

:

이하 생략
</location>
</body>
</description>
</item>
</channel>
</rss>

 

- 우선 특정 태그명의 첫번째 element 값 가져오는 메소드 만들기

/*================
 * XMLDOM.java
 *============== */

package com.test.xml;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class XMLDOM
{
	public static String getText(Element parent, String tagName)
	{
		String result ="";
		
		// 대상 태그(tagName) 객체의 첫 번째 자식 노드 얻어오기
		Node node = parent.getElementsByTagName(tagName).item(0);
		Element element = (Element)node;
		
		// 대상 엘리먼트(element) 의 자식 노드(텍스트 노드)의 값 얻어오기
		result = element.getChildNodes().item(0).getNodeValue();
		
		return result;
	}
}

- 해당 값으로 Java console 실행 시켜서 원하는 지역의 기상 데이터 얻어내기

/*===========================================================================
 * XmlDomTest06.java
 * - 콘솔 기반 프로그램
 * - XML DOM 활용 → 원격 (remote) XML 읽어내기
 *   (rss.xml)
 *   ※ 기상청 날씨 누리로 부터 얻어낸 데이터
 *   https://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=109
===========================================================================*/

/*
 stnId=108 전국
 stnId=109 서울, 경기
 stnId=105 강원
 stnId=131 충북
 stnId=133 충남
 stnId=146 전북
 stnId=156 전남
 stnId=143 경북
 stnId=159 경남
 stnId=184 제주특별자치도
 */

package com.test.xml;

import java.io.InputStream;
import java.net.URL;
import java.util.Scanner;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.sun.corba.se.spi.orbutil.fsm.Input;

public class XmlDomTest06
{
	public static void main(String[] args)
	{
		/*
		https://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=%s
		에서 %s 값이 아래 리스트의 값에 따라 지역별 일기예보 정보가 나타나는 것을 확인
		 */
		Scanner sc = new Scanner(System.in);
		String[] stnId = {"108","109","105","131","133","146","156","143","159","184"};
		
		do
		{
			try
			{
				DocumentBuilderFactory  builderFactory = DocumentBuilderFactory.newInstance();
				DocumentBuilder builder = builderFactory.newDocumentBuilder();
				Document xmlObj = null;
								
				// 외부의 입력값 처리
				System.out.println("■■■기상청 육상 중기 예보■■■");
				System.out.println("--------------------------------------------");
				System.out.println("1. 전국    ");
				System.out.println("2. 서울, 경기 ");
				System.out.println("3. 강원     ");
				System.out.println("4. 충북     ");
				System.out.println("5. 충남     ");
				System.out.println("6. 전북     ");
				System.out.println("7. 전남     ");
				System.out.println("8. 경북     ");
				System.out.println("9. 경남     ");
				System.out.println("10. 제주특별자치도");
				System.out.println("--------------------------------------------");
				System.out.println(">> 지역 선택 입력 (종료 0) : ");
				
				String m = sc.next();
				if (m.equals("0"))
					break;
				
				// 지역 선택 값을 입력 받아 stnId= 뒤에 파라미터로 넘겨주는 형태의 문자열을 만든다.
				String str = String.format("https://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=%s"
						, stnId[Integer.parseInt(m)-1]);
				
				// 위에서 구성한 xml 주소 + stnId 값을 URL로 사용하게끔 처리
				URL url = new URL(str);
				
				// URL 로 접근하여 XML의 데이터 내용 읽어오기 (스트림)
				// url을 열었을 때 stream으로 받아서 inputSource 처리하여 가져온다.
				InputSource is = new InputSource(url.openStream());
				xmlObj = builder.parse(is);
				
				// ----------------------------------------------------------------------------------------------------
				
				// xml로부터 받아온 모든 태그를 Element 데이터 타입으로
				Element root = xmlObj.getDocumentElement();
				
				// 전체 태그들 중 첫 번째 item 태그
				// 전체 태그들 중 item 이란 태그가 하나밖에 없어서 데이터타입 Node
				Node itemNode = root.getElementsByTagName("item").item(0);
				Element itemElement = (Element)itemNode;
				
				// item의 첫 번째 하위 태그들 중 title 태그
				// <title>서울,경기도 육상 중기예보 - 2023년 07월 25일 (화)요일 06:00 발표</title> 의
				// 엘리먼트 (XMLDOM 클래스에서는 맨 상위 태그의 첫 번째 엘리먼트 값)
				System.out.printf("%s%n%n", XMLDOM.getText(itemElement, "title"));
				
				// item 태그 아래 전체 태그 중 wf란 이름을 가진 첫 번째 태그
				// 한반도 전반 기상 정보를 감싸고 있는 태그
				Node wfNode = root.getElementsByTagName("wf").item(0);
				// 그 태그의 값 --> 한반도 전반 기상 정보
				Element wfElement = (Element)wfNode;
				
				System.out.println("[기상전망]--------------------------------------------------");
				System.out.printf("%s%n%n", wfElement.getTextContent().replaceAll("<br />",  "\n"));
				
				System.out.println("[육상날씨]--------------------------------------------------");
				// 전체 태그 들중 location 이라는 태그가 여러 개 있어서 데이터타입 NodeList
				NodeList locationNodeList = root.getElementsByTagName("location");
				
				for (int i = 0; i < locationNodeList.getLength(); i++)
				{
					// 특정 지역 정보를 감싸고 있는 i번째 태그
					Node locationNode = locationNodeList.item(i);
					// 그 태그의 값 --> 특정 지역(loaction)의 하위 태그들
					Element locationElement = (Element)locationNode;
					
					// 특정 지역(loaction)의 하위 태그들 중 city 태그의 값(첫번째 값)
					System.out.printf("도시 : %s%n", XMLDOM.getText(locationElement, "city"));
					System.out.println("---------------------------------------------------------");
					
					// 그 특정 지역의 도시의 일기 예보들 (시간 별로 여러개의 data 태그가 있음)
					NodeList dataNodeList = locationElement.getElementsByTagName("data");
					
					// 시간 단위 수 만큼 --> 그 도시의 시간별 태그 수 만큼 반복
					for (int j = 0; j < dataNodeList.getLength(); j++)
					{
						//특정 도시의 시간 태그:data 태그들 중 j번째 태그
						Node dataNode = dataNodeList.item(j);
						// 그 태그의 값들(속 태그들)
						Element dataElement = (Element)dataNode;
						
						// 중 태그 명이 tmEf, wf, tmn 등의 속 태그 안에 있는 데이터
						System.out.printf(" %s / %s / %s℃~ %s℃ / 강수 %s%%%n"
										,XMLDOM.getText(dataElement, "tmEf")
										,XMLDOM.getText(dataElement, "wf")
										,XMLDOM.getText(dataElement, "tmn")
										,XMLDOM.getText(dataElement, "tmx")
										,XMLDOM.getText(dataElement, "rnSt"));
					}
					
					System.out.println("----------------------------------------------------------");
				}
				
			} 
			catch (Exception e)
			{
				System.out.println(e.toString());
			}
			
		} while (true);
	}
}

- 실행 결과

'java 메모' 카테고리의 다른 글

JAVA 접근 제어자 및 필드 속성 정리  (0) 2025.01.10
Java #포맷 변경 - 문자열 -> 날짜  (0) 2023.09.18