도서 5권에 대해서 제목, 저자, 출판일, 가격에 대한 정보를 나타내는 표를 xml파일을 가져와 만들어보자.
첫번째로, xml파일을 만든다. (파일명: books.xml)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book>
<title>Java의 정석</title>
<author>남궁성</author>
<date>2016/06/17</date>
<price>30000</price>
</book>
<book>
<title>이것이 MySQL이다</title>
<author>우재남</author>
<date>2022/06/14</date>
<price>32000</price>
</book>
<book>
<title>미움 받을 용기</title>
<author>기시미 이치로</author>
<date>2022/12/28</date>
<price>14310</price>
</book>
<book>
<title>멈추면, 비로소 보이는 것들</title>
<author>혜민</author>
<date>2017/03/15</date>
<price>12600</price>
</book>
<book>
<title>완벽하지 않은 것들에 대한 사랑</title>
<author>혜민</author>
<date>2016/02/03</date>
<price>13320</price>
</book>
</books>
|
cs |
위 코드에 간단한 설명을 덧붙이자면,
<?xml version="1.0" encoding="UTF-8"?> 는 XML 프롤로그(prolog)
<books> 부터 </books>는 XML 요소
XML은 HTML과 같이 트리(tree) 형태의 계층 구조를 가진다. 따라서, <books>는 루트(root) 요소에 해당한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div id="demo"></div>
<script type="text/javascript">
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
xmlProc(xhttp);
}
}
xhttp.open("GET", "books.xml", true);
xhttp.send();
function xmlProc(xml) {
let xmlDoc = xml.responseXML;
let rootTagName = xmlDoc.documentElement.nodeName;
let nodeArr = xmlDoc.documentElement.childNodes;
let nodeName;
for (i = 0; i < nodeArr.length; i++) {
if (nodeArr[i].nodeType == 1) {
nodeName = nodeArr[i].nodeName;
console.log(nodeName);
}
}
let table = "<table border='1'>";
table += "<col width='50'><col width='100'><col width='140'><col width='100'><col width='140'>";
table += "<tr>";
table += "<th>번호</th>";
columnName = xmlDoc.getElementsByTagName(nodeName)[0];
let child = columnName.firstChild;
console.log(columnName.childNodes.length);
for (i = 0; i < columnName.childNodes.length; i++) {
if (child.nodeType == 1) {
table += "<th>" + child.nodeName + "</th>";
console.log(child.nodeName);
}
child = child.nextSibling;
}
table += "</tr>";
let len = xmlDoc.getElementsByTagName(nodeName).length;
for (i = 0; i < len; i++) {
table += "<tr>";
table += "<th>" + (1 + i) + "</th>";
let dataArr = xmlDoc.getElementsByTagName(nodeName)[i];
child = dataArr.firstChild;
for (j = 0; j < dataArr.childNodes.length; j++) {
if (child.nodeType == 1) {
table += "<td>" + child.childNodes[0].nodeValue
+ "</td>";
}
child = child.nextSibling;
}
table += "</tr>";
}
table += "</table>"
document.getElementById("demo").innerHTML = table;
}
</script>
</body>
</html>
|
cs |
먼저, <div id="demo"></div>를 작성하여 완성된 table이 위치할 공간을 만든다.
<script>안의 코드들을 부분씩 떼어내서 살펴보면,
아래 코드는 자바스크립트를 사용해서 XMLHttpRequest 객체를 전송하는 것이다.
1
2
3
4
5
6
7
8
9
|
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if(this.readyState == 4 && this.status == 200){
xmlProc( xhttp );
}
}
xhttp.open("GET", "books.xml", true);
xhttp.send();
|
cs |
1. XMLHttpRequest 객체의 생성
XMLHttpRequest 객체는 서버로부터 XML 데이터를 전송받아 처리하는 데 사용된다.
2. xhttp.onreadystatechange = function() {
}
onreadystatechange와 연결된 이벤트 핸들러 코드를 추가한다.
onreadystatechange 프로퍼티는 XMLHttpReuest 객체의 readyState 프로퍼티의 값이 변할 때마다 자동으로 호출되는 함수를 설정한다.
이때, readyState 프로퍼티란 XMLHttpRequest 객체의 현재 상태를 나타낸다.
객체의 현재 상태에 따라서 다음과 같은 주기로 변화하는데,
- UNSENT (숫자 0) : XMLHttpRequest 객체가 생성됨.
- OPENED (숫자 1) : open() 메소드가 성공적으로 실행됨.
- HEADERS_RECEIVED (숫자 2) : 모든 요청에 대한 응답이 도착함.
- LOADING (숫자 3) : 요청한 데이터를 처리 중임.
- DONE (숫자 4) : 요청한 데이터의 처리가 완료되어 응답할 준비가 완료됨.
3. if(this.readyState == 4 && this.status == 200){
xmlProc( xhttp );
}
2번에서 설명한 것과 같이 this.readyState == 4는 요청한 데이터의 처리가 완료되어 응답할 준비가 완료됐음을 의미한다. 이는 this.readyState == this.DONE으로 대체할 수 있다.
xmlProc( xhttp );는 이후 코드에서 xmlProc() 함수를 정의하여 사용한다.
4. open(), send()
open(method, url, async)을 이용했다.
이때, method는 요청방식으로 GET 또는 POST 방식이 있다.
GET 방식은 POST 방식보다 간단하고 빠르며, 대부분 경우에 사용이 가능하다.
url은 불러올 파일의 주소를 적는다.
async는 true(비동기) 또는 false(동기)를 적는데, 서버 요청은 true를 사용해야 하고, true(비동기)의 경우 JavaScript는 서버 응답을 기다릴 필요가 없으며 서버 응답을 기다리는 동안 다른 작업을 수행하다가 응답이 준비되면 처리가 가능하다.
open()에서 GET 방식을 사용했기 때문에 send()를 사용하여 서버에 요청을 보내도록 한다.
이후 코드들에 대해서는 주석을 통해 설명하도록 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Books</title>
</head>
<body>
<div id="demo">
</div>
<script type="text/javascript">
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if(this.readyState == 4 && this.status == 200){
xmlProc( xhttp );
}
}
xhttp.open("GET", "books.xml", true);
xhttp.send();
function xmlProc( xml ) {
// responseXML 프로퍼티: 서버에 요청하여 응답으로 받은 데이터를 XML DOM 객체로 저장한다.
let xmlDoc = xml.responseXML; // 요청한 데이터를 XML DOM 객체로 반환함
// root명 취득
// xmlDoc.documentElement: xmlDoc의 루트 요소를 반환
// xmlDoc.documentElement.nodeName: xmlDoc의 루트 요소의 노드 이름을 반환
let rootTagName = xmlDoc.documentElement.nodeName;
// alert(rootTagName); // books
// node명 취득
// xmlDoc.documentElement.childNodes: xmlDocdml 자식 노드 리스트를 반환
let nodeArr = xmlDoc.documentElement.childNodes;
console.log(nodeArr.length); // <book>과 텍스트 노드의 개수 등의 개수
// node list 확인
// nodeArr(자식 노드 리스트)에는 각 요소 다음에 별도의 텍스트 노드가 존재한다. 따라서, nodeType 프로퍼티를 통해 요소 노드만 선택하도록 한다.
// 요소 노드의 경우 nodeType 프로퍼티 값이 1이다.
let nodeName;
for(i = 0;i < nodeArr.length; i++){
if(nodeArr[i].nodeType == 1){
nodeName = nodeArr[i].nodeName; // 요소 노드들의 이름을 반환
console.log(i); // 요소 노도들의 인덱스
console.log(nodeName); // <book>
}
}
// table을 준비
let table = "<table border='1'>";
table += "<col width='50'><col width='100'><col width='140'><col width='100'><col width='140'>";
table += "<tr>"; // 1번째 row 시작
// column명(tag명)을 취득
// getElementsByTagName("태그명"): 특정 태그 이름을 가지는 모든 요소를 노드 리스트의 형태로 반환합니다.
columnName = xmlDoc.getElementsByTagName(nodeName)[0]; // <book> 5개중 첫번째 <book>
console.log(columnName);
// 콘솔 결과
// <book>
// <num>1</num>
// <title>Java의 정석</title>
// <author>남궁성</author>
// <date>2016/06/17</date>
// <price>30000</price>
// </book>
let child = columnName.firstChild;
console.log(columnName.childNodes.length); // 11
console.log(child); // #text
for(i = 0;i < columnName.childNodes.length; i++){
if(child.nodeType == 1){ // 요소 노드들만 선택되도록
table += "<th>" + child.nodeName + "</th>";
console.log(child.nodeName);
}
child = child.nextSibling; // nextSibling: 다음 요소를 반환(요소, 텍스트 등)
}
table += "</tr>"; // 1번째 row 끝
// data 출력 // 2~6번째 row들
let len = xmlDoc.getElementsByTagName(nodeName).length;
console.log(len);
console.log(xmlDoc.getElementsByTagName(nodeName)[1]);
// 콘솔 결과
// <book>
// <num>2</num>
// <title>이것이 MySQL이다</title>
// <author>우재남</author>
// <date>2022/06/14</date>
// <price>32000</price>
// </book>
for(i = 0;i < len; i++){
table += "<tr>";
let dataArr = xmlDoc.getElementsByTagName(nodeName)[i];
child = dataArr.firstChild;
for(j = 0;j < dataArr.childNodes.length; j++){
if(child.nodeType == 1){
table += "<td>" + child.childNodes[0].nodeValue + "</td>";
}
child = child.nextSibling;
}
table += "</tr>";
}
table += "</table>"
document.getElementById("demo").innerHTML = table;
}
</script>
</body>
</html>
|
cs |