[XML]

[XmlStudy] 20240202 [프로그램 소스]

Jelly-fish 2024. 2. 2. 13:22

XmlStudy

 

체크할 사항

 

Ⅰ. 대상 태그를 이용한 자식 노드, 자식 노드의 텍스트 노드 얻어오기

 

XMLDOM 클래스에 선언한 메소드

`String getText(Element parent, String tagName)`

 

대상 태그(tagName) 객체의 첫 번째 자식 노드 얻어오기
Node node = parent.getElementsByTagName(tagName).item(0);
Element element = (Element)node;

 

대상 엘리먼트(element)의 자식 노드(텍스트 노드)의 값 얻어오기
String result = element.getChildNodes().item(0).getNodeValue();

Ⅱ. 기상전망에 해당하는 `wf` 노드에 접근하여, 텍스트 노드의 `<br />` 문자열을 `\n` 으로 변경

Node wfNode = root.getElementsByTagName("wf").item(0);

Element wfElement = (Element)wfNode;

System.out.println("기상전망 : " + wfElement.getTextContent().replaceAll("<br />", "\n"));
                                                            ★────────── ========  ======
                                                                        변경할 대상 변경할 문자

Ⅲ. 원격(remote) XML 읽어내기 (`https://fs.jtbc.co.kr/RSS/newsflash.xml`)

로컬(local) XML 파일을 읽어낼 때와의 유일한 차이점

 

① 문자열로 구성한 요청 주소를 URL 객체로 구성한다. → 절대 경로 지정 방식 
String str = "http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=156";
URL url = new URL(str);

 

 

이때, 웹 상의 요청 방식은 절대 경로 지정방식이다.

URL 객체로 구성하는 이유는, 해당 URL 주소로 접근하여 XML 형식으로 작성된 문자열(String)을

얻어오기 위함이다.

 

② 구성한 URL 로 접근하여 데이터 내용 읽어오기 → 스트림(Stream)
InputSource is = new InpurSource(url.openStream());
xmlObj = builder.parse(is);

 

`InputSource` 객체를 생성한 후, 생성자의 매개변수로 `InputStream`을 넘겨준다.

URL 객체의 openStream() 메소드를 호출하면, url 객체에 해당하는 inputStream 얻어낼 수 있다.


Ⅳ. `getElementsByTagName("name")` 메소드를 사용하지 않고 특정 노드의 각기 다른 하위 노드들의 노드명과, 텍스트 노드 값을 가져오기

 

가져와야 하는 XML 파일이 아래와 같은 형식일 경우, `<item>` 태그 내부의 하위 노드들의 정보를

모두 출력하기 위해서는 root 엘리먼트인 `<rss>` 에 접근한 후 `<item>` 엘리먼트에서 `getElementsByTagName("name")`

처리를 하는 것이 일반적일 것이다.

<rss version="2.0">
    <channel>
        <title>JTBC News</title>
        <link>https://fs.jtbc.co.kr/RSS/newsflash.xml</link>
        <description>속보 RSS</description>
        <language>ko</language>
        <copyright>Copyright(C) JTBC All rights reserved.</copyright>
        <category>속보</category>
        <pubDate>2024년 2월 5일 월요일 오후 11:55:00</pubDate>
        『출력하고 싶은 XML 의 노드 → <item> 노드 내부의 모든 항목』
        ───────────────────────────────────────────────────────────────────
        <item>
            <title>2월 5일 (월) 뉴스룸 다시보기</title>
            <link>https://news.jtbc.co.kr/article/article.aspx?news_id=NB12164050</link>
            <description> 시청자 여러분 JTBC 뉴스룸을 시작하겠습니다. 삼성전자 이재용 회장이 '경영권 불법 승계 의혹'과 관련해 1심에서 무죄를 선고받았습니다. 경영권을 물려받기 위해 그룹 내 회사들을 불공정하게 합병했고, 이 과정</description>
            <pubDate>2024.02.05</pubDate>
        </item>
        ───────────────────────────────────────────────────────────────────
....

 

그런데, 만약 태그가 현재처럼 4개가 아니라 굉장히 많은 숫자이고 일일이 태그명을 `getElementsByTagName("name")` 메소드의 매개변수로 넣어주는 것은 굉장히 번거로울 것이다.

 

이때는, `getChildNodes()` 메소드와 `item(i)`, `getNodeName()` 메소드를 이용하여 태그명을 일일이 나열하지 않고도

처리할 수 있다.

 

  • ① 루트 엘리먼트에서 `<item>` 노드에 해당하는 NodeList itemList 를 반환받는다.
  • itemList의 길이만큼 반복하면서 아래를 반복한다. `『for i』`
    • itemNode를 얻어낸다. 
    • itemNode 를 다운캐스팅하여 itemElement 를 얻어낸다.
    • itemElement 에 해당하는 자식 노드들의 NodeList childNodeList 를 얻어낸다.
    • ⑷ ⑶에서 반환받은 childNodeList 의 길이만큼 반복하면서 `『for j』` item(j)를 통해 ★childNodeList의 j번째 노드명을 구한다.
    • ⑸ i번째에 해당하는 itemNode에 대한 itemElement에서 위에서 구한 노드명에 해당하는 텍스트 노드를 구해낸다.
NodeList itemList = root.getElementsByTagName("item");

for (int i = 0; i < itemList.getLength(); i++)
{
    Node itemNode = itemList.item(i);
    Element itemElement = (Element)itemNode;

    NodeList childNodeList = itemElement.getChildNodes();

	// <item> 노드 하위에 있는 자식 노드들의 개수만큼 아래를 반복한다.
    for (int j = 0; j<childNodeList.getLength(); j++)
    {
        System.out.printf("%s>%s%n"
                    //-- <item> 노드의 자식 노드들 노드명을 하나씩 꺼내온다.
                    , childNodeList.item(j).getNodeName()
                    //-- 위에서 꺼낸 <item> 노드의 자식 노드명에 해당하는 태그의
                    //   텍스트 노드를 꺼내온다.
                    , XmlDom.getText(itemElement, String.valueOf(childNodeList.item(j).getNodeName())));

    }

}

 


XmlApp05


 

XML DOM 활용 → 로컬(local) XML 읽어내기 (rss.xml)
※ 기상청 날씨누리로부터 얻어낸 데이터

 

기상청 날씨누리 페이지에서 기상정보 xml 조회

 

 


실행 결과 콘솔창

01
XmlDomTest06.java [전국 기상 정보 Local에서 조회]


Java Resources > src > com.test

XmlDom
/*=====================
       XMLDOM.java
=======================*/
package com.test;

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();
		
//		result = String.format("%s : %s"
//						, element.getChildNodes()
//						, element.getChildNodes().item(0).getNodeValue());
//		
//		result.replaceAll("text", "");
		
		return result;
		
	}
}

 


Java Resources > src > com.test

XmlDomTest06
/*=================================================
     XmlDomTest06.java
     - 콘솔 기반 자바 프로그램
     - XML DOM 활용 → 로컬(local) XML 읽어내기
       (rss.xml)
       ※ 기상청 날씨누리로부터 얻어낸 데이터
===================================================*/

package com.test;

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;

public class XmlDomTest06
{
	public static void main(String[] args)
	{
		try
		{
			// 1. XML 파일 메모리에 로드
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			
			
			String url = "rss.xml";
			Document xmlObj = builder.parse(url);
			
			// 2. 루트 엘리먼트 접근
			Element root = xmlObj.getDocumentElement();
			
			// 3-1. 타이틀 추출하기
			Node itemNode = root.getElementsByTagName("item").item(0);
			Element itemElement = (Element)itemNode;
			
			
			System.out.printf("%s%n%n", XmlDom.getText(itemElement, "title"));
			//--==>> 전국 육상 중기예보 - 2024년 02월 02일 (금)요일 06:00 발표 

			// 3-2. 기상전망 추출하기
			Node wfNode = root.getElementsByTagName("wf").item(0);
			//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
			// itemElement → description → header → wf 로 접근하는 것이 아니라
			// root 엘리먼트를 통해 곧바로 wf 노드에 접근할 수 있다는 것을 알아두도록 하자!
			//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
			Element wfElement = (Element)wfNode;
			
			System.out.println("[기상전망] ------------------------------------------------------");
			System.out.printf("%s%n%n", wfElement.getTextContent().replaceAll("<br />", "\n"));
			
			// 3-3. 도시별 기상 예보 추출하기
			
			System.out.println("[육상날씨] ------------------------------------------------------");

			NodeList locationNodeList = root.getElementsByTagName("location");
			
			for (int i = 0; i < locationNodeList.getLength(); i++)
			{
				Node locationNode = locationNodeList.item(i);
				Element locationElement = (Element)locationNode;
				
				System.out.printf("도시 : %s%n", XmlDom.getText(locationElement, "city"));
				System.out.println("----------------------------------------------------");
				
				
				NodeList dataNodeList = locationElement.getElementsByTagName("data");
				//Node dataNode = dataNodeList.item(0);
				//Element dataElement = (Element)dataNode;
				
				//NodeList subNodeList = dataElement.getChildNodes();
				
				/*
					<mode>A02</mode>				
					<tmEf>2024-02-05 00:00</tmEf>	// 날짜 시간
					<wf>흐리고 비/눈</wf>			// 
					<tmn>2</tmn>
					<tmx>3</tmx>
					<reliability />
					<rnSt>70</rnSt>
				*/
				
				// [선생님 풀이]
				for (int k = 0 ; k < dataNodeList.getLength(); k++)
				{
					Node dataNode = dataNodeList.item(k);
					Element dataElement = (Element)dataNode;
					
					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"));
				}
				
				
				// [내 풀이] - 잘못됨, 시간별로 하나씩만 나온다.
//				for (int j = 0; j < dataNodeList.getLength(); j++)
//				{
//					Node subNode = subNodeList.item(j);
//					
//					if (subNode.getNodeType() == 1)
//					{
//						Element subElement = (Element)subNode;
//						
//						// reliablility(신뢰도) 값이 없으므로, 태그명을 이용하여 이 항목 제외하기.
//						if (!subElement.getNodeName().equals("reliability"))	
//						{
//							System.out.printf("%s : %s %n", subElement.getNodeName(), subElement.getTextContent());
//						}
//						// 태그 안의 텍스트 노드 값이 존재하지 않을 때 항목 제외하기
//						if (!subElement.getTextContent().equals(""))
//						{
//							System.out.printf("%s : %s %n", subElement.getNodeName(), subElement.getTextContent());
//						}
//					}
//					
//				}
				
				Node rnStNode = locationElement.getElementsByTagName("rnSt").item(0);
				Element rnStElement = (Element)rnStNode;
				System.out.printf("%s : %s%n", rnStElement.getNodeName(), XmlDom.getText(locationElement, "rnSt"));
				
				
				
				
				
				
				System.out.println();
				
			}
			
			
			
		} catch (Exception e)
		{
			System.out.println(e.toString());
		}
	}
}

XmlApp05

rss.xml [기상청 날씨누리에서 받아온 전국 육상 중기예보 xml 파일]
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>기상청 육상 중기예보</title>
		<link>http://www.kma.go.kr/weather/forecast/mid-term_01.jsp</link>
		<description>기상청 날씨 웹서비스</description>
		<language>ko</language>
		<generator>기상청</generator>
		<pubDate>2024년 02월 02일 (금)요일 06:00</pubDate>
		<item>
			<author>기상청</author>
			<category>육상중기예보</category>
			<title>전국 육상 중기예보 - 2024년 02월 02일 (금)요일 06:00 발표</title>
			<link>http://www.kma.go.kr/weather/forecast/mid-term_01.jsp</link>
			<guid>http://www.kma.go.kr/weather/forecast/mid-term_01.jsp</guid>
			<description>
				<header>
					<title>전국 육상중기예보</title>
					<tm>202402020600</tm>
					<wf>
<![CDATA[ ○ (강수) 5일(월)은 전국에 비 또는 눈이 오겠으며, 강원영동은 6일(화) 오전까지 이어지겠습니다.<br />○ (기온) 이번 예보기간 아침 기온은 -9~5도, 낮 기온은 2~10도로 평년(최저기온 -9~1도, 최고기온 3~10도)과 비슷하거나 조금 높겠습니다.<br />○ (해상) 5일(월)~6일(화)은 대부분 해상에서 물결이 1.0~4.0m로 매우 높게 일겠습니다.<br /><br />* 5일(월)~6일(화)은 기압골의 발달 정도와 이동 속도에 따라 강수지역과 시점, 강수형태(비/눈)가 변동될 가능성이 있으니, 앞으로 발표되는 최신 예보를 참고하기 바랍니다. ]]>
					</wf>
				</header>
				<body>
					<location wl_ver="3">
						<province>서울ㆍ인천ㆍ경기도</province>
						<city>서울</city>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 00:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>2</tmn>
							<tmx>3</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 12:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>2</tmn>
							<tmx>3</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 00:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-2</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 12:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-2</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-2</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-2</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-10 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-11 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-12 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-5</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
					</location>
					<location wl_ver="3">
						<province>서울ㆍ인천ㆍ경기도</province>
						<city>인천</city>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 00:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>2</tmn>
							<tmx>2</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 12:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>2</tmn>
							<tmx>2</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 00:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-2</tmn>
							<tmx>3</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 12:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-2</tmn>
							<tmx>3</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>3</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>3</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-10 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-11 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-12 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
					</location>
					<location wl_ver="3">
						<province>서울ㆍ인천ㆍ경기도</province>
						<city>수원</city>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 00:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>3</tmn>
							<tmx>3</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 12:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>3</tmn>
							<tmx>3</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 00:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-2</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 12:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-2</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-10 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-11 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-4</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-12 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-6</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
					</location>
					<location wl_ver="3">
						<province>서울ㆍ인천ㆍ경기도</province>
						<city>파주</city>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 00:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>1</tmn>
							<tmx>2</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 12:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>1</tmn>
							<tmx>2</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 00:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-4</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 12:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-4</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-6</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-6</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-6</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-6</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-7</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-7</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-10 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-7</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-11 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-7</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-12 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-8</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
					</location>
					<location wl_ver="3">
						<province>서울ㆍ인천ㆍ경기도</province>
						<city>이천</city>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 00:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-05 12:00</tmEf>
							<wf>흐리고 비/눈</wf>
							<tmn>3</tmn>
							<tmx>4</tmx>
							<reliability />
							<rnSt>70</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 00:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-2</tmn>
							<tmx>6</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-06 12:00</tmEf>
							<wf>구름많음</wf>
							<tmn>-2</tmn>
							<tmx>6</tmx>
							<reliability />
							<rnSt>30</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-07 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-3</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-5</tmn>
							<tmx>6</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-08 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-5</tmn>
							<tmx>6</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-5</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A02</mode>
							<tmEf>2024-02-09 12:00</tmEf>
							<wf>맑음</wf>
							<tmn>-5</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-10 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-5</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-11 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-6</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
						<data>
							<mode>A01</mode>
							<tmEf>2024-02-12 00:00</tmEf>
							<wf>맑음</wf>
							<tmn>-7</tmn>
							<tmx>5</tmx>
							<reliability />
							<rnSt>10</rnSt>
						</data>
					</location>
                    
				....(중략)
	</channel>
</rss>

 

XmlApp06


XML DOM 활용
Remote XML 읽어내기 (http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108)
※ 기상청 날씨누리로부터 얻어낸 데이터
사용자의 지역 선택값 (1 ~ 10) 에 따라 웹 브라우저에서 읽어들이는 xml 링크가 달라진다. (GET 방식!)

실행 결과 콘솔창

0123
XmlDomTest07.java [기상청 날씨누리 xml 이용]


Java Resources > src > com.test

XmlDomTest07
/*=================================================
     XmlDomTest07.java
     - 콘솔 기반 자바 프로그램
     - XML DOM 활용 → 로컬(local) XML 읽어내기
       (http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108)
       ※ 기상청 날씨누리로부터 얻어낸 데이터
===================================================*/

/*
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108	전국
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=109	서울·경기도
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=105	강원도
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=131	충청북도
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=133	충청남도
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=146	전라북도
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=156	전라남도
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=143	경상북도
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=159	경상남도
http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=184	제주특별자치도
*/

package com.test;

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.xml.sax.InputSource;

public class XmlDomTest07
{
	// 1. 사용자에게 원하는 지역 선택값을 입력받는다.
	// 2. 사용자가 선택하면, 그 지역에 해당하는 XML 을
	//    실시간으로 웹 사이트에서 불러와서 정보를 뿌려주도록 처리한다.
	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		String[] stnId = {"108", "109", "105", "131", "133", "146", "156", "143", "159", "184"};
		
		do
		{
			try
			{
				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
				DocumentBuilder builder = factory.newDocumentBuilder();
				Document xmlObj = null;
				
				// Local XML 파일인 경우...
				// 내부 파일 경로 파일명, builder.parse(url) 사용.
				/*
				String url = "rss.xml";
				xmlObj = builder.parse(url);
				*/
				
				// Remote XML 파일인 경우...
				
				// 안내 → 외부의 입력값 처리
				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.print(">> 지역 선택(종료 0) : ");
				
				String m = sc.next();
				if (m.equals("0"))
					break;
				
				//System.out.println("계속 진행");
				
				String str = String.format("http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=%s"
							 			  , stnId[Integer.parseInt(m)-1]);
				
				// 확인
				System.out.println("요청 주소 : " + str);
				// 『3. 강원도』 선택 시
				//--==>> 요청 주소 : http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=105
				
				// 『7. 전라남도』 선택 시
				//--==>> 요청 주소 : http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=156
				
				// * (웹 상의 요청 방식은 절대 경로 지정 방식이다.)
				// 문자열로 구성한 요청 주소를 URL 객체 구성 → 절대 경로 지정 방식
				URL url = new URL(str);
				//==================================================================================
				// [Why?] 왜 URL 객체로 구성? → 해당 URL 에 접근해서 String 을 얻어오기 위함이다.
				//==================================================================================
				
				// 구성한 URL 로 접근하여 데이터 내용 읽어오기 → 스트림(stream)
				InputSource is = new InputSource(url.openStream());
				
				
				
				
			} catch (Exception e)
			{
				System.out.println(e.toString());
			}
			
			
		} while (true);
		
		
	}

}

 


 

XmlApp07


- XML DOM 활용 → 원격(remote) XML 읽어내기 (https://fs.jtbc.co.kr/RSS/newsflash.xml)
※ 언론사 뉴스로부터 얻어낸 데이터

 

JTBC 뉴스 RSS 페이지에서 속보 xml 조회

 

01


실행 결과 콘솔창

01
XmlDomTest08.java [JTBC 속보 xml 출력]

 


( * 선생님 해설은 내일! 2024/02/03~)

 

Java Resources > src > com.test 

XmlDomTest08.java
/*=================================================
     XmlDomTest08.java
     - 콘솔 기반 자바 프로그램
     - XML DOM 활용 → 원격(remote) XML 읽어내기
       (https://fs.jtbc.co.kr/RSS/newsflash.xml)
       ※ 언론사 뉴스로부터 얻어낸 데이터
===================================================*/

/*
title> JTBC News
link>https://fs.jtbc.co.kr/RSS/newsflash.xml
description>속보 RSS
copyright>Copyright(C) JTBC All rights reserved.

주요 기사 -----------------------------------------------------------
title>[날씨] 전국 대체로 흐림…곳곳 미세먼지 '나쁨'
description> 오늘(2일)은 전국이 대체로 흐린 가운데, 일부 지역의 미세먼지가 '나쁨' 수준을 보이겠습니다.낮 최고기온은 3도에서 10도로 포근한 날씨가 예상됩니다.
link>https://news.jtbc.co.kr/article/article.aspx?news_id=NB12163616
pubDate>2024.02.02

title>외식비 급등에 인기 '쑥'…냉동치킨 '영양성분' 꼭 확인하세요
description> [앵커]프랜차이즈 치킨값이 2만 원을 훌쩍 넘는 요즘, 대체품으로 마트의 냉동 치킨을 찾는 경우가 늘어났습니다. 그런데 잘 살펴보셔야 합니다. 인기 제품들 가운데 포화지방과 나트륨이 과하게 들어 있거나, 원산
link>https://news.jtbc.co.kr/article/article.aspx?news_id=NB12163595
pubDate>2024.02.02
*/

package com.test;

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;

public class XmlDomTest08
{
//	public static void main(String[] args)
//	{
//		/*
//		1. 원격 XML 정보를 요청하고, 그 결과를 메모리에 로드
//		   → XML DOM 구성
//		    ·DB 활용
//		    ·DBF 활용
//		    ·XML 로딩
//		2. 루트 엘리먼트 접근
//		3. 특정 하위 엘리먼트 접근
//		4. 텍스트 노드 접근
//		   → 필요한 데이터 획득
//		5. 결과 처리(출력)
//		*/
//		
//		try
//		{
//			// ※ DOM(Document Object Model)
//			//    - XML 이나 HTML Document(문서)를 응용프로그램에서 사용하기 위한 API 규칙
//			//	  - DOM 은 Document(문서)의 각 부분들을 객체(Object)로 표현한 API
//			
//			// ※ DOM(Document Object Model) 파서(Parser)
//			//    - XML 문서를 읽고, 해석한 후,
//			//      해석한 결과를 메모리에 DOM 객체 트리 구조로 생성시키는 파서(Parser)
//			//    - 원하는 데이터에 접근할 수 있도록 해주어
//			//      대상 데이터를 검색, 수정, 삭제할 수 있도록 지원
//			
//			
//			
//		} catch (Exception e)
//		{
//			System.out.println(e.toString());
//		}
//	}
	
	
	
	public static void main(String[] args)
	{
		try
		{
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document xmlObj = null;
			
			String str = "https://fs.jtbc.co.kr/RSS/newsflash.xml";
			URL url = new URL(str);
			InputSource is = new InputSource(url.openStream());
			
			xmlObj = builder.parse(is);
			
			
			Element root = xmlObj.getDocumentElement();
			
			// 타이틀, 날짜

			System.out.printf("title> %s%n", XmlDom.getText(root, "title"));
			System.out.printf("link> %s%n", XmlDom.getText(root, "pubDate"));
			System.out.printf("description> %s%n", XmlDom.getText(root, "description"));
			System.out.printf("copyright> %s%n", XmlDom.getText(root, "copyright"));

			System.out.println();
			System.out.println("주요 기사 ---------------------------------------------------");
			
			/*
			title>외식비 급등에 인기 '쑥'…냉동치킨 '영양성분' 꼭 확인하세요
			description> [앵커]프랜차이즈 치킨값이 2만 원을 훌쩍 넘는 요즘, 대체품으로 마트의 냉동 치킨을 찾는 경우가 늘어났습니다. 그런데 잘 살펴보셔야 합니다. 인기 제품들 가운데 포화지방과 나트륨이 과하게 들어 있거나, 원산
			link>https://news.jtbc.co.kr/article/article.aspx?news_id=NB12163595
			pubDate>2024.02.02
			*/
			NodeList itemList = root.getElementsByTagName("item");
			
			
			
			for (int i = 0; i < itemList.getLength(); i++)
			{
				Node itemNode = itemList.item(i);
				Element itemElement = (Element)itemNode;
				
				NodeList childNodeList = itemElement.getChildNodes();
				
				for (int j = 0; j<childNodeList.getLength(); j++)
				{
					//System.out.println("테스트: " + itemElement.getChildNodes().item(i).getNodeName());
					
					System.out.printf("%s>%s%n"
								, childNodeList.item(j).getNodeName()	
								, XmlDom.getText(itemElement, String.valueOf(childNodeList.item(j).getNodeName())));
					
				}
				
//				System.out.printf("title>%s%n", XmlDom.getText(itemElement, "title"));
//				System.out.printf("description>%s%n", XmlDom.getText(itemElement, "description"));
//				System.out.printf("link>%s%n", XmlDom.getText(itemElement, "link"));
//				System.out.printf("pubDate>%s%n", XmlDom.getText(itemElement, "pubDate"));
				System.out.println("-------------------------------------------------------------");
				
			}
			
			
			
			
			
		} catch (Exception e)
		{
			System.out.println(e.toString());
		}
	}
	

}