XML 기본문법
XML이란?
- 일반 TXT파일은 데이터 내용을 구분할 수 없다.
- 이때 내용을 구분할 수 있게 하는 형식이 탄생했는데 그것이 XML과 JSON이다.
- 그 중 XML은 포맷형식이 운영체제마다 동일하기 때문에, 어떤 운영체제를 쓰던지 동기화 가능하다.
- 기존의 모든 프레임워크들은 Spring도 있고 MyBaits, IBatis, Hibernate들이 있는데, 이들이 전부 XML을 사용한다.
- Spring과 가장 어울리는 것이 MyBatis이다.
- Struts와 가장 어울리는 것은 Hibernate이다.
XML을 사용하는 이유는?
- HTML은 웹 페이지에서 데이터베이스처럼 구조화된 데이터를 지원할 수 없지만 XML은 사용자가 구조화된 데이터베이스를 뜻대로 조작할 수 있다.
- XML은 데이터를 문서로 저장해서 오라클 없이도 데이터를 가져와서 쓰기 위함이 기본 목적이다.
XML파싱이란?
- XML 문서 내 태그들의 속성값을 읽어 오는 과정이라고 할 수 있다.
XML 파싱의 종류
1. JAXB
- 외부에서 데이터를 XML로 보내는 경우에 주로 사용함
- Java와 XML을 연결하는 라이브러리임
2. JAXP
(1) DOM
- XML을 메모리에 저장하고 제어함
- 수정, 삭제, 추가, 검색이 가능함
- 단점 : 속도가 늦음
- XML을 오라클 대신 사용할 때 주로 사용함
- 거의 사용하지 않음
(2) SAX
- 검색만 가능함(데이터 읽기만 가능)
- MyBatis와 Spring이 주로 사용함
- 기억해야 하는 이유 : 에러가 주로 SAX에서 발생하기 때문이다.
XML태그란?
- 사용자 정의 태그이다.
- 고정태그가 아니기 때문에 어떤 목적으로 만들었는지 알 수 없다.
- 업체에서 제공하는 XML태그만 사용해야 한다.
- MyBatis는 구글에서 인수했기 때문에, 구글에서 제공하는 XML 태그나 속성만 사용해야 한다.
- XML태그와 속성이 어떤게 있는지 알 수 없기 때문에,
어떤 태그가 있는지 태그나 속성의 목록을 제공해주는 것이 DTD파일이다.
XML태그의 구조
- [태그명+구조]로 되어 있다.
(1)
<태그>데이터저장</태그>
<td>데이터 출력</td> ==> text()
(2)
<태그속성="데이터 저장"/>
<img src=""/> ==> attr("src")
- 문법사항은 DTD안에 있는 태그나 속성만 사용해야 한다.
- HTML은 자유롭게 사용할 수 있다는 점이 차이점이다.
XML 데이터 읽는 방법
1. JAXB
(1) 자바 클래스와 XML의 태그를 매칭시켜야 한다.
- 태그 안에 태그가 있는 경우에는 자바 클래스로 제작해야 한다.
- 태그 안에 문자열(데이터)가 있는 경우에는 자바 변수로 제작해야 한다.
- XML데이터를 자바변수에 저장하는 방법을 ‘언마샬‘이라고 한다.
- 자바 변수를 XML데이터로 출력하는 방법을 ‘마샬‘이라고 한다.
- 데이터가 오라클에 저장되어 있으면 실시간 변경을 할 수 없다.
- 실시간 변경을 위해서는 웹사이트를 크롤링해야하는데 이때 알아야 하는 것이 XML이다.
- 데이터를 읽어와서 출력하는데 사용자가 보기 쉽게 하는 것을 CSS라고 한다.
<rss> <!--Rss클래스-->
<channel> <!--channel클래스-->
<item> <!--item클래스-->
<title>aaa</title> <!--title변수-->
<img>aaa</img> <!--img변수-->
<link>aaa</link> <!--link변수-->
</item>
</channel>
</rss>
(2) 루트 클래스 = Rss클래스 제작
- rss태그가 전체 태그를 감싸고 있기 때문에 root임
package com.sist.xml;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Rss {
private Channel channel= new Channel();
public Channel getChannel() {
return channel;
}
public void setChannel(Channel channel) {
this.channel = channel;
}
}
(3) Channel클래스 제작
- 밑에 50개의 Item 태그를 가지고 있기 때문에 List에 데이터를 모아주어야 한다.
package com.sist.xml;
import java.util.*;
public class Channel {
private List<Item> list = new ArrayList<Item>();
public List<Item> getList() {
return list;
}
public void setList(List<Item> list) {
this.list = list;
}
}
(4) Item클래스 제작
package com.sist.xml;
public class Item {
private String title;
private String description;
private String author;
private String link;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
(5) XML에 있는 데이터를 채우는 클래스 제작
package com.sist.xml;
import java.util.*;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import com.sun.jmx.remote.internal.Unmarshal;
import java.net.*;
public class NewsManager {
public List<Item> newsAllData(String fd)
{
List<Item> list = new ArrayList<Item>();
try {
// 1. 웹사이트에 연결
/*
where=rss(XML로 전송 받는 부분)
query=(사용자가 보내준 검색이를 받는 부분)
- 한글을 보내게 되면 반드시 인코딩해서 보내야함
- 인코딩 할 때 사용하는 api : import java.net.*
- 웹서버에 데이터 전송 시 인코딩해서 전송하는 메소드 : URLEncoder
*/
String strUrl="http://newssearch.naver.com/search.naver?where=rss&query="
+ URLEncoder.encode(fd,"UTF-8");
// 2. 실제 연결하는 클래스 : URL
URL url= new URL(strUrl);
// 3. 명령을 내리기
/*
- @XMLRootElemnet가 붙어 있는 클래스를 보내야함
*/
JAXBContext jb=JAXBContext.newInstance(Rss.class);
// 4. 파싱을 해서 데이터를 읽어온 뒤, 자바 클래스에 값을 넣어주도록 설정 요청
Unmarshaller un=jb.createUnmarshaller();
// 5. 값을 채워주기
Rss rss= (Rss) un.unmarshal(url);
list=rss.getChannel().getItem();
} catch (Exception e) {}
return list;
}
}
(6) news.jsp 제작
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*, com.sist.xml.*"%>
<%
// 데이터 읽어가는 과정 및 순서
// 6. 한글을 한글로 변환(디코딩)
request.setCharacterEncoding("UTF-8");
// 1. 사용자가 보내준 검색어 읽어오기
String fd=request.getParameter("fd");
// 2. 주의점 : 맨 처음에는 검색어를 보내줄 수 없어서, default로 설정해야함
if(fd==null)
{
fd="맛집";
}
// 3. 네이버로 연결해서 데이터를 읽어오는 역할의 클래스
NewsManager m = new NewsManager();
// 4. 네이버로부터 데이터 수집
List<Item> list = m.newsAllData(fd);
// 5. 화면에 출력하기
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
/*
<오버라이딩>
이미 만들어진 css를 변경하는 부분
*/
.row{
width:800px;
margin:0px auto; /* 가운데 정렬 */
}
h1{
text-align: center; /* 문자열을 가운데 정렬 */
}
.title{
font-size: 25px;
color: #FC6;
}
</style>
</head>
<body>
<!-- 1. 전체 테두리 만들기 : 960px (양쪽에 약간의 여백을 가지고 있음)-->
<div class="container">
<!-- 2. 타이틀 만들기 -->
<div class="row">
<h1>네이버 실시간 뉴스 검색</h1>
<!-- 3. 검색창 만들기 -->
<table class="table">
<tr>
<td>
<form method="post" action="news.jsp">
<input type=text name=fd size=15 class="input-sm">
<input type=submit value="검색" class="btn btn-sm btn-primary">
</form>
</td>
</tr>
</table>
<!-- 4. 뉴스 데이터를 출력하는 위치 -->
<table class="table table-striped">
<tr>
<td>
<%
for(Item i:list)
{
%>
<table class="table table-hover">
<tr>
<td class="text-center title">
<%=i.getTitle() %>
</td>
</tr>
<tr>
<td><%=i.getDescription() %></td>
</tr>
<tr>
<td>
<a href="<%=i.getLink()%>">
<%=i.getDescription()%>
</a>
</td>
</tr>
<tr>
<td class="text-right">
<%=i.getAuthor() %>
</td>
</tr>
</table>
<%
}
%>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>
2. DOM
(1) 테이블과 동일한 형식으로 XML파일 제작
<?xml version="1.0" encoding="UTF-8"?>
<sawon> <!-- 테이블명 -->
<list> <!-- Record, Row -->
<sabun>1</sabun> <!-- Column명 -->
<name>홍길동</name>
<dept>개발부</dept>
<job>사원</job>
<sal>3000</sal>
</list>
<list>
<sabun>2</sabun>
<name>심청이</name>
<dept>개발부</dept>
<job>대리</job>
<sal>3800</sal>
</list>
<list>
<sabun>3</sabun>
<name>박문수</name>
<dept>총무부</dept>
<job>과장</job>
<sal>4500</sal>
</list>
</sawon>
3. DOM : 속성값을 불러오는 방법
(1) XML 데이터 만들기
<?xml version="1.0" encoding="UTF-8"?>
<sawon_list>
<sawon sabun="1" name="홍길동" dept="개발부"/>
<sawon sabun="2" name="홍길은" dept="총무부"/>
<sawon sabun="3" name="홍길금" dept="기획부"/>
<sawon sabun="4" name="김길동" dept="영업부"/>
<sawon sabun="5" name="이길동" dept="자재부"/>
</sawon_list>
(2) 만든 XML 데이터 읽어오기
package com.sist.dom;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
public class DomManager2 {
public static void main(String[] args) {
try {
// 1. 파서기를 생성
// * 파서기의 역할 : xml데이터를 메모리에 트리형태로 저장하는 장치
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 2. 파서기를 이용하기
DocumentBuilder db = dbf.newDocumentBuilder();
// 3. XML을 읽어서 트리형태로 메모리에 저장하기
Document doc=db.parse(new File("C:\\webDev\\20200917-JxspStudy1\\src\\com\\sist\\dom\\sawon2.xml"));
// 4. 최상위 태그(XMLRootElement)가져오기
// * 최상위태그=테이블명 *
Element root=doc.getDocumentElement();
System.out.println(root.getTagName());
// 5. sawon태그를 묶어서 처리하기
NodeList list=root.getElementsByTagName("sawon");
System.out.println(list.getLength());
// 6. for문 돌려서 속성값들 가져오기
for(int i=0;i<list.getLength();i++)
{
// (1) 사원태그를 한 개씩 읽어오기
Element sawon=(Element)list.item(i);
String sabun=sawon.getAttribute("sabun");
String name=sawon.getAttribute("name");
String dept=sawon.getAttribute("dept");
System.out.println(sabun+" "+name+" "+dept );
}
} catch (Exception e) {}
}
}
4. SAX
(1) XMLParser 클래스 제작
- SAXParser 재정의? 오버라이딩?
package com.sist.dom;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XMLParser extends DefaultHandler{
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// System.out.println(qName+"태그 읽기 시작");
if(qName.equals("sawon"))
{
String sabun=attributes.getValue("sabun");
String name=attributes.getValue("name");
String dept=attributes.getValue("dept");
System.out.println(sabun+" "+name+" " +dept);
}
// XML읽을 때, 태그명과 속성명이 일치해야 함!
}
@Override
public void startDocument() throws SAXException {
System.out.println("XML문서가 시작!!");
}
@Override
public void endDocument() throws SAXException {
System.out.println("XML 문서 읽기 종료!!");
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println(qName+"태그 읽기 종료");
}
}
(2) SAXManager 클래스 파일 제작하기
package com.sist.dom;
import java.io.*;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class SAXManager {
public static void main(String[] args) {
try {
// 1. SAX파서기를 생성하는 클래스 만들기
SAXParserFactory spf=SAXParserFactory.newInstance();
// 2. SAX파서기 가져오기
SAXParser sp=spf.newSAXParser();
// 3. 파일 읽기 요청하기
XMLParser xp=new XMLParser();
//
sp.parse(new File("C:\\webDev\\20200917-JxspStudy1\\src\\com\\sist\\dom\\sawon2.xml"), xp);
} catch (Exception e) {}
}
}
메모리에 저장되는 형식
1. List 방식
- 일반 변수, 클래스
2. Tree 방식
- DOM파싱하면 트리 형식으로 저장됨
- Document
- 태그는 Elemnet
- NodeList
- TextNode
- ML (HTML , XML)
- Document Object Model (DOM)
- Simple API for XML (SAX)