ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [XML] 004. XML 관찰 실습(4)(JSP 기반) : XPath 개요
    SsY/Class 2023. 7. 27. 10:10
    728x90
    XPath 의 개요
    ■■■ XPath (XML Path Language) ■■■
    
    ○ XPath 개요
    
       - XPath 는 XSLT 표준의 주요 요소이다.
       - XPath 를 사용하여 XML 문서의 요소 및 속성을 탐색할 수 있다.
       - XPath 는 경로 표현식을 활용하여 XML 문서에 노드를 식별하고 탐색한다.
       - XPath 는 W3C 권장 사항이다.
       
    ○ XPath 의 경로 표현식 (XPath Path Expressions)
    
       - XPath 는 경로 표현식을 사용하여 XML 문서에서 Node 또는 NodeSet(NodeList) 을 선택한다.
       - 이러한 경로 표현식은 기존 파일 시스템에서 사용하는 경로 표현식과 매우 유사하다
       
    ○ XPath 의 표준 기능 (XPath Standard Functions)
    
       - XPath 에는 200 개 이상의 내장 기능이 포함되어 있다.
       - 문자열 값 (string value), 숫자 값(numeric values)
         , 부울(booleans), 날짜 및 시간 비교(date and time comparison)
         , 노드 조작(node manipulation), 시퀀스 조작(sequence manipulation) 등을 위한 기능이 있다.
       - 현재 XPath 표현식은 Javascript, JAVA, XML 스키마, PHP, Python, C, C++ 및 기타 여러 언어에서도 사용할 수 있다.
       
    ○ XPath 주요 용어
    
       - 노드
         · XPath 에는 요소, 속성, 텍스트, 네임스페이스, 처리명령, 주석, 문서 이렇게 총 7가지 노드가 있다.
         · XML 문서는 노드 트리로 다루어지며 트리의 최상위 요소를 루트 요소라고 한다.
       - 원자값 (Atomic values)
         · 원자 값은 자식이나 부모가 없는 노드이다.
       - 아이템 (Items)
         · 아이템(Items)은 원자값 또는 노드이다.
       
       <bookstore>                                        → <bookstore>  → Node (root Element)
       	<book>                                            → <book>       → Node (element node)
       		<title lang="en">Harry Potter</title>         → <title>      → Node (element node)
       		       ---------                              → lang="en"    → Node (attribute node)
       		       ---------                              → lang="en"    → 원자 값(automic values)
       		<author>J K. Rowling</author>
       		        ------------                          → J K. Rowling → 원자 값(automic values)
       		<year>2005</year>                             
       		<price>29.99</price>                          
       	</book>
       </bookstore>
       
    ○ 노드의 관계 (Relationship of Nodes)
    
       - 부모
       - 자식
       - 형제, 자매
       - 선조, 조상
       - 자손
       
    ○ 노드 선택 (Selection Nodes)
    
       - XPath 는 경로 표현식을 사용하여 XML 문서에서 Node 를 선택한다
       - 경로 또는 단계에 따라 Node 가 선택된다
       
       ===================  ===============================================================
       Expression           Description
       ===================  ===============================================================
       nodename             이름이 "nodename" 인 모든 노드를 선택한다
       -------------------  ---------------------------------------------------------------
       /                    루트 노드에서 선택한다 
       -------------------  ---------------------------------------------------------------
       //                   현재 노드에서 선택한 위치에 상관없이 문서의 노드를 선택한다.   
       -------------------  ---------------------------------------------------------------
       .                    현재 노드를 선택한다
       -------------------  ---------------------------------------------------------------
       ..                   현재 노드의 부모노드를 선택한다.
       -------------------  ---------------------------------------------------------------
       @                    속성을 선택한다.
       ===================  ===============================================================
                            
                            ▼
                            
       ===================  ===============================================================
       Expression           Description
       ===================  ===============================================================
       bookstore            이름이 "bookstore" 인 모든 노드를 선택한다.
       -------------------  ---------------------------------------------------------------
       /bookstore           루트 요소인 bookstore를 선택한다
                            이 때, 표현식으로 사용되는 경로가
                            『/』 로 시작하면 요소의 절대 경로를 나타낸다.
       -------------------  ---------------------------------------------------------------
       bookstore/book       bookstore 의 하위인 모든 book 요소를 선택한다.
       -------------------  ---------------------------------------------------------------
       //book               문서 상 어느 위치에 존재하든 모든 book 요소를 선택한다.
       -------------------  ---------------------------------------------------------------
       bookstore//book      bookstore 의 하위 요소인 모든 book 요소를 선택한다.
       -------------------  ---------------------------------------------------------------
       //@lang              lang 이라는 모든 속성을 선택한다.
       ===================  ===============================================================
       
    ※ 경로 표현식의 추가 옵션
    
       - 표현식 : /bookstore/book[1]
         내용   : bookstore 요소의 하위 첫 번째 book 요소를 선택한다.
                  단, IE 5 ~ 9 브라우저에서 첫 번째 노드는 [0] 이다.
                  하지만, W3C 규칙을 준수하는 다른 브라우저에서 첫 번째 노드는 [1] 이다.
                  따라서 IE 에서 발생하는 이 문제를 해결하기 위해서는 
                  SelectionLanguage 를 XPath 로 설정해야한다.
    
       - 표현식 : /bookstore/book[last()]
         내용   : bookstore 요소의 하위인 마지막 book 요소를 선택한다.
    
       - 표현식 : /bookstore/book[position()<3]
         내용   : bookstore 요소의 하위인 처음 두 개의 book 요소를 선택한다.
    
       - 표현식 : //title[@lang]
         내용   : lang 이라는 속성을 가진 모든 title 요소를 선택한다.
    
       - 표현식 : //title[@lang='en']
         내용   : lang 속성의 값이 en 인 모든 title 요소를 선택한다.
    
       - 표현식 : /bookstore/book[price>35.00]
         내용   : price 가 35.00 보다 큰 요소가 있는 bookstore 요소의 모든 book 요소를 선택한다.

    XmlApp08
    - 날씨 RSS 
    • Weather.jsp - 뷰 페이지 구성 (정적 템플릿)
      WeatherInfo.jsp - 데이터 바인딩한 뷰 페이지

    더보기
    <%@ page contentType="text/html; charset=UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%
    	request.setCharacterEncoding("UTF-8");
    	String cp = request.getContextPath();
    %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Weather.jsp</title>
    <link rel="stylesheet" type="text/css" href="css/main.css">
    
    <!-- jQuery 추가 -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <!-- 부트스트랩 CDN // 부가적 테마만 제외 -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    
    <!--
    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	// 제주특별자치도
    -->
    
    <div class="container">
    
       <h2>
          기상 정보 <small>중기 예보</small>
       </h2>
       
       <div class="panel-group" role="group">
          
          <div class="panel panel-default" role="group">
          
             <div class="panel-heading">지역 선택</div>
             <div class="panel-body">
                <form method="get" role="form">
                   <input type="radio" name="stnId" value="108" checked="checked"> 전국
                   <input type="radio" name="stnId" value="109"> 서울, 경기
                   <input type="radio" name="stnId" value="105"> 강원
                   <input type="radio" name="stnId" value="131"> 충북
                   <input type="radio" name="stnId" value="133"> 충남
                   <input type="radio" name="stnId" value="146"> 전북
                   <input type="radio" name="stnId" value="156"> 전남
                   <input type="radio" name="stnId" value="143"> 경북
                   <input type="radio" name="stnId" value="159"> 경남
                   <input type="radio" name="stnId" value="184"> 제주특별자치도
                   
                   <button type="submit" class="btn btn-default">Submit</button>
                </form>
             </div><!-- close .panel-body -->
          
          </div><!-- close. panel-default -->
          <br>
          <div class="panel panel-default" role="group">
             <div class="panel-heading">기상 정보 출력 </div>
             <div class="panel-body">
                <p>
                   <b> 전국 육상 중기예보 - </b>
                </p>
                   
                <p>
                    ○ (강수) 29일..<br>
                    ○ (기온)       <br>
                    ○ (주말전망)   <br>
                        
                    * 이번 예보기간에는..<br>
                </p>
                
                <h3>서울</h3>
                <table class="table">
                   <thead>
                   <tr>
                      <th>날짜</th>
                      <th>날씨</th>
                      <th>최저/최고 기온</th>
                      <th>강수확률</th>
                   </tr>
                   </thead>
                   
                   <tbody>
                      <tr>
                         <td>2023-07-29 00:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-29 12:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-30 00:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-29 12:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                   </tbody>
                </table>
                
                <h3>인천</h3>
                <table class="table">
                   <thead>
                   <tr>
                      <th>날짜</th>
                      <th>날씨</th>
                      <th>최저/최고 기온</th>
                      <th>강수확률</th>
                   </tr>
                   </thead>
                   
                   <tbody>
                      <tr>
                         <td>2023-07-29 00:00</td>
                         <td><img src="images/NB08.png"/>흐리고 비</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-29 12:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-30 00:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-29 12:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                   </tbody>
                </table>   
                
             </div><!-- close .panel-body -->
          </div><!-- close. panel-default -->
          
          
          
       </div><!-- close .panel-group -->
    </div>
    
    
    </body>
    </html>
    <%@page import="com.test.xml.WeatherDTO"%>
    <%@page import="java.util.ArrayList"%>
    <%@page import="com.test.xml.WeatherDAO"%>
    <%@ page contentType="text/html; charset=UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%
    	request.setCharacterEncoding("UTF-8");
    	String cp = request.getContextPath();
    %>
    <%
    	// 사용자가 선택한 지역 데이터 수신
    	String stnId = request.getParameter("stnId");
    	
    	if (stnId==null)	// 최초 요청일 때
    		stnId = "108";	//-- 전국 날씨 정보
    		
    	StringBuffer sb = new StringBuffer();
    	WeatherDAO dao = new WeatherDAO(stnId);
    	
    	// 타이틀 
    	String title = dao.weatherTitle();
    	
    	// 날씨 예보 개요
    	String weatherInfo = dao.weatherInfo();
    	
    	// 도시 정보 및 날짜 시간 별 날씨 정보
    	ArrayList<String> cityList = dao.weatherCityList();
    	for (int i=0; i<cityList.size(); i++)
    	{
    		sb.append(String.format("<h3>%s</h3>", cityList.get(i)));
    		
    		//-- 1 부터 시작!
    		ArrayList<WeatherDTO> weatherList = dao.weatherList(String.valueOf(i+1));
    		
    		// 테이블 동적 생성
    		sb.append("<table class='table'>");
    		
    		sb.append("<tr>");
    		sb.append("<th>날짜</th>");
    		sb.append("<th>날씨</th>");
    		sb.append("<th>최저/최고 기온</th>");
    		sb.append("<th>강수확률</th>");
    		sb.append("</tr>");
    		
    		for (WeatherDTO w : weatherList)
    		{
    			sb.append("<tr>");
    			sb.append(String.format("<td>%s</td>", w.getTmEf()));								// 날짜
    			sb.append(String.format("<td><img src='images/%s'>%s</td>", w.getImg(),w.getWf()));	// 날씨
     			sb.append(String.format("<td>%s℃ / %s℃</td>", w.getTmn(), w.getTmx()));			// 최저 / 최고 기온
    			sb.append(String.format("<td>%s%%</td>", w.getRnSt()));								// 강수확률
    			sb.append("</tr>");
    		}
    
    		sb.append("</table>");
    	}
    	
    %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>WeatherInfo.jsp</title>
    <link rel="stylesheet" type="text/css" href="css/main.css">
    
    <!-- jQuery 추가 -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <!-- 부트스트랩 CDN // 부가적 테마만 제외 -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    
    <script type="text/javascript">
    	$(function()
    	{
    		//확인
    		//alert("확인");
    		
    		// 선택한 라디오 버튼의 상태를
    		// 요청 이후에도 선택된 상태로 유지할 수 있도록 처리
    		//$(":radio:eq(0)").attr("checked","checked");	//-- 전국
    		//$(":radio:eq(2)").attr("checked","checked");	//-- 강원
    		//$(":radio:eq(9)").attr("checked","checked");	//-- 제주
    		
    		//$(":radio[value='109']").attr("checked","checked");	//-- 서울,경기
    		//$(":radio[value='131']").attr("checked","checked");	//-- 충북
    		//$(":radio[value='184']").attr("checked","checked");	//-- 제주 
    		
    		$(":radio[value='<%=stnId %>']").attr("checked","checked");
    		
    	});
    </script>
    
    </head>
    <body>
    
    <div class="container">
    
       <h2>
          기상 정보 <small>중기 예보</small>
       </h2>
       
       <div class="panel-group" role="group">
          
          <div class="panel panel-default" role="group">
          
             <div class="panel-heading">지역 선택</div>
             <div class="panel-body">
             	<!-- action 속성 지정 안함 → 요청페이지/데이터 수신처 는 자기자신 -->
                <form method="get" role="form">
                   <label><input type="radio" name="stnId" value="108"> 전국 </label>
                   <label><input type="radio" name="stnId" value="109"> 서울, 경기 </label> 
                   <label><input type="radio" name="stnId" value="105"> 강원 </label>
                   <label><input type="radio" name="stnId" value="131"> 충북 </label>
                   <label><input type="radio" name="stnId" value="133"> 충남 </label>
                   <label><input type="radio" name="stnId" value="146"> 전북 </label>
                   <label><input type="radio" name="stnId" value="156"> 전남 </label>
                   <label><input type="radio" name="stnId" value="143"> 경북 </label>
                   <label><input type="radio" name="stnId" value="159"> 경남 </label>
                   <label><input type="radio" name="stnId" value="184"> 제주특별자치도 </label>
                   
                   <button type="submit" class="btn btn-default">Submit</button>
                </form>
             </div><!-- close .panel-body -->
          
          </div><!-- close. panel-default -->
          <br>
          <div class="panel panel-default" role="group">
             <div class="panel-heading">기상 정보 출력 </div>
             <div class="panel-body">
                <p>
                   <!-- <b> 전국 육상 중기예보 - </b> -->
                   <b>	<%=title %> </b>
                </p>
                   
                <p>
                	<!-- 
                    ○ (강수) 29일..<br>
                    ○ (기온)       <br>
                    ○ (주말전망)   <br>
                        
                    * 이번 예보기간에는..<br>
                    -->
                    <%=weatherInfo %>
                </p>
                
                <!-- 
                <h3>서울</h3>
                <table class="table">
                   <thead>
                   <tr>
                      <th>날짜</th>
                      <th>날씨</th>
                      <th>최저/최고 기온</th>
                      <th>강수확률</th>
                   </tr>
                   </thead>
                   
                   <tbody>
                      <tr>
                         <td>2023-07-29 00:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-29 12:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-30 00:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-29 12:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                   </tbody>
                </table>
                
                <h3>인천</h3>
                <table class="table">
                   <thead>
                   <tr>
                      <th>날짜</th>
                      <th>날씨</th>
                      <th>최저/최고 기온</th>
                      <th>강수확률</th>
                   </tr>
                   </thead>
                   
                   <tbody>
                      <tr>
                         <td>2023-07-29 00:00</td>
                         <td><img src="images/NB08.png"/>흐리고 비</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-29 12:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-30 00:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                      <tr>
                         <td>2023-07-29 12:00</td>
                         <td><img src="images/NB03.png"/>구름많음</td>
                         <td>25 / 31</td>
                         <td>30</td>
                      </tr>
                   </tbody>
                </table>   
    			-->
    			<%=sb.toString() %>            
             </div><!-- close .panel-body -->
          </div><!-- close. panel-default -->
          
       </div><!-- close .panel-group -->
    </div>
    
    </body>
    </html>

    • WeatherDTO.java
    /*====================
       WeatherDTO.java
    =====================*/
    
    package com.test.xml;
    
    public class WeatherDTO
    {
    	// 주요 속성 구성
    	private String tmEf, wf, tmn, tmx, rnSt, img; 
    	//-- tmEf      → 날짜와 시간 태그
    	//                2013-11-24 00:00
    	
    	//-- wf        → 날씨 예보 태그
    	//               ○ 맑음
    	//               ○ 구름조금
    	//               ○ 구름많음, 구름많고 비, 구름많고 비/눈, 구름많고 눈/비,구름많고 눈
    	//               ○ 흐림, 흐리고 비, 흐리고 비/눈, 흐리고 눈/비, 흐리고 눈
    	
    	//-- tmn       → 최저온도 태그
    	//                (21 → 21℃)	→『ㄹ』
    	
    	//-- tmx       → 최고온도 태그
    	//                (30 → 30℃)	→『ㄹ』
    	
    	//-- rnSt      → 강수확률 태그
    	//                (40 → 40%)
    	
    	//-- img       → 날씨 예보에 따른 이미지
    
    	// getter / setter 구성
    	public String getTmEf()
    	{
    		return tmEf;
    	}
    
    	public void setTmEf(String tmEf)
    	{
    		this.tmEf = tmEf;
    	}
    
    	public String getWf()
    	{
    		return wf;
    	}
    
    	public void setWf(String wf)
    	{
    		this.wf = wf;
    	}
    
    	public String getTmn()
    	{
    		return tmn;
    	}
    
    	public void setTmn(String tmn)
    	{
    		this.tmn = tmn;
    	}
    
    	public String getTmx()
    	{
    		return tmx;
    	}
    
    	public void setTmx(String tmx)
    	{
    		this.tmx = tmx;
    	}
    
    	public String getRnSt()
    	{
    		return rnSt;
    	}
    
    	public void setRnSt(String rnSt)
    	{
    		this.rnSt = rnSt;
    	}
    
    	public String getImg()
    	{
    		return img;
    	}
    
    	public void setImg(String img)
    	{
    		this.img = img;
    	}
    	
    	
    }

    • WeatherDAO.java
    /*============================================================================
       WeatherDAO.java
       - DAO 구성
       - XML DOM 활용 → 원격 XML 읽어내기
         (https://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108)
    ============================================================================ */
    
    package com.test.xml;
    
    import java.io.IOException;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.HashMap;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.xpath.XPath;	//check
    import javax.xml.xpath.XPathConstants;
    import javax.xml.xpath.XPathExpressionException;
    import javax.xml.xpath.XPathFactory;	// check
    
    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 org.xml.sax.SAXException;
    
    public class WeatherDAO
    {
    	// 주요 속성 구성 (공통 멤버)
    	private Document xmlObj;
    	private XPath xPath;
    	private HashMap<String, String> map;
    	
    	// 생성자 정의 → 기본 생성자
    	public WeatherDAO() throws ParserConfigurationException, IOException, SAXException
    	{
    		this("108");	// 전국 기준
    		/*
    		stnId=108	// 전국
    		stnId=109	// 서울,경기
    		stnId=105	// 강원
    		stnId=131	// 충북 
    		stnId=133	// 충남 
    		stnId=146	// 전북
    		stnId=156	// 전남
    		stnId=143	// 경북
    		stnId=159	// 경남
    		stnId=184	// 제주특별자치도
    		*/
    	}
    	
    	// 생성자 정의 → 매개 변수 있는 생성자
    	public WeatherDAO(String stnId) throws ParserConfigurationException, IOException, SAXException
    	{
    		map = new HashMap<String, String>();
    		/*
    		맑음, 구름조금, 구름많음, 구름많고 비, 구름많고 비/눈, 구름많고 눈/비,구름많고 눈
    		, 흐림, 흐리고 비, 흐리고 비/눈, 흐리고 눈/비, 흐리고 눈        
    		*/
    		
    		map.put("맑음", "W_DB01.png");
    		map.put("흐림", "W_DB04.png");
    		map.put("비", "W_DB05.png");
    		map.put("구름조금", "W_NB02.png");
    		map.put("구름많음", "W_NB03.png");
    		map.put("흐리고 비", "W_NB08.png");
    		map.put("구름많고 비", "W_NB20.png");
    
    		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    		DocumentBuilder builder = factory.newDocumentBuilder();
    		//-- DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    		//   와 같은 구문
    		
    		String str = String.format("https://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=%s"
    				, stnId);
    		URL url = new URL(str);
    		InputSource is = new InputSource(url.openStream());
    		
    		xmlObj = builder.parse(is);
    		xPath = XPathFactory.newInstance().newXPath();	//-- check 
    		//-- XPathFactory xFactory = XPathFactory.newInstance();
    		//   xPath = xFactory.newXPath();
    		//   와 같은 구문
    		
    		/*
    		○ XPath 생성
    		   - XPathFactory 의 정적 메소드(static) 『newInstance()』 호출을 통해
    		     XPath 의 생성을 지원하는 XPathFactory 를 생성하고
    		   - 이 XPathFactory 의 정적 메소드(static) 『newPath()』 호출을 통해
    		     XPath 객체를 생성한다.
    		     
    		○ 노드 선택 (Selecting Nodes)
    		   - 브라우저마다 XPath 를 처리하는 방법에서 차이를 보인다.
    		   - Chrome, FireFox, Edge, Opera, Safari 등은
    		     『evaluation()』 메소드를 사용하여 노드를 처리한다.
    		     → xmlDoc.evaluation(xPath, xmlDoc, null, XPathResult.ANY_TYPE, null)
    		   - IE 는 『selectNodes()』 메소드를 사용하여 노드를 선택한다.
    		   
    		○ XPath 의 『compile(XPath 경로 표현식)』
    		   - XML 데이터 Parsing
    		     1. XML 이 제공되는 URL 로 접속하여 데이터를 수신한다.
    		     2. DocumentBuilderFactory ... newInstance() 로 factory 를 생성한다.
    		     3. DocumentBuilder ... newDocumentBuilder() 로 builder 를 생성한다.
    		     4. InputSource is ... new InputSource() 로 InputSource 를 생성한다.
    		        이 때, 파일로 수신한 경우라면 File 객체를 넘겨준다.
    		     5. Document xmlObj = builder.parse(is) 로 XML 을 파싱(Parsing)한다.
    		     6. XPath xPath = XPathFactory.newInstance().newXPath() 로
    		        XPath 객체를 생성하고
    		     7. XPathExpression expr = XPath.compile( XPath  경로 표현식 ) 으로
    		        가져올 Element 를 선택하게 된다.
    		     8. 해당 노드(Element) 에 접근하여 필요한 데이터를 추출한다.
    		*/
    		
    	}
    	
    	// 단일 값 처리 
    	// <title>중기예보~~~</title>
    	public String weatherTitle() throws XPathExpressionException
    	{
    		String result = "";
    		
    		result = xPath.compile("/rss/channel/item/title").evaluate(xmlObj);
    		
    		return result;
    	}
    	
    	// <wf><![CDATA[ ○ ~~~~ ]]></wf>
    	public String weatherInfo() throws XPathExpressionException
    	{
    		String result = "";
    		
    		result = xPath.compile("/rss/channel/item/description/header/wf").evaluate(xmlObj);
    		
    		return result;
    	}
    	
    	// check -- XPath 사용시 가장 많이 사용하는 방법
    	// 다중 엘리먼트 city (도시 이름) → 배열 구성
    	public ArrayList<String> weatherCityList() throws XPathExpressionException
    	{
    		ArrayList<String>result = new ArrayList<String>();
    		
    		NodeList cityNodeList = (NodeList)xPath
    									.compile("/rss/channel/item/description/body/location/city")
    									.evaluate(xmlObj, XPathConstants.NODESET);
    		/*
    		○ XPath 의 『evaluate()』 메소드 두 번째 파라미터 (리턴 타입)
    		   - XPathConstants.NODESET		-- NodeList
    		   - XPathConstants.NODE
    		   - XPathConstants.BOOLEAN
    		   - XPathConstants.NUMBER
    		   - XPathConstants.STRING
    		*/
    		
    		for (int i=0; i<cityNodeList.getLength(); i++)
    		{
    			Node cityNode = cityNodeList.item(i);
    			result.add(cityNode.getTextContent());
    		}
    		
    		return result;
    	}
    	
    	// check
    	// 날씨 정보 리스트 -- 반환 자료형 주의 
    	public ArrayList<WeatherDTO> weatherList(String idx) throws XPathExpressionException
    	{
    		ArrayList<WeatherDTO> result = new ArrayList<WeatherDTO>();
    		
    		// check! 특정 지역의 data들 반환
    		NodeList dataNodeList = (NodeList)xPath
    									.compile(String.format("/rss/channel/item/description/body/locatios[%s]/data", idx))
    									.evaluate(xmlObj, XPathConstants.NODESET);
    
    		// check! → 『int i=1;』
    		//for (int i=0; i<dataNodeList.getLength(); i++)
    		//-- W3C 의 권고에 따라 잘 만들어진 웹 페이지의 경우... 1부터 시작 
    		for (int i=1; i<=dataNodeList.getLength(); i++)
    		{
    			// tmEf
    			String tmEf = (String)xPath
    				.compile(String.format("/rss/channel/item/description/body/locations[%s]/data[%s]/tmEf", idx, i))
    				.evaluate(xmlObj);
    			
    			// wf
    			String wf = (String)xPath
    				.compile(String.format("/rss/channel/item/description/body/locations[%s]/data[%s]/wf", idx, i))
    				.evaluate(xmlObj);
    			
    			// tmn
    			String tmn = (String)xPath
    				.compile(String.format("/rss/channel/item/description/body/locations[%s]/data[%s]/tmn", idx, i))
    				.evaluate(xmlObj);
    		
    			// tmx
    			String tmx = (String)xPath
    				.compile(String.format("/rss/channel/item/description/body/locations[%s]/data[%s]/tmx", idx, i))
    				.evaluate(xmlObj);
    			
    			// rnSt
    			String rnSt = (String)xPath
    				.compile(String.format("/rss/channel/item/description/body/locations[%s]/data[%s]/rnSt", idx, i))
    				.evaluate(xmlObj);
    			
    			// DTO 구성
    			WeatherDTO w = new WeatherDTO();
    			w.setTmEf(tmEf);
    			w.setWf(wf);
    			w.setTmn(tmn);
    			w.setTmx(tmx);
    			w.setRnSt(rnSt);
    			
    			// ++ HashMap 에 구성해둔 img 가져오기
    			w.setImg(map.get(wf));
    			
    			result.add(w);
    		}
    		
    		return result;
    	}
    	
    	
    }
    728x90
Designed by planet-si