노드에 접근하는 법
HTML이나 XML 같은 문서에서 노드(node), 즉 태그나 요소들을 어떻게 접근할까
getElementsByTagName() 메서드를 사용하는 방법: 이 메서드는 특정 태그 이름을 가진 모든 요소들을 반환해준다.
예를 들어, p 태그로 된 모든 요소를 가져오고 싶으면
document.getElementsByTagName("p") 이렇게 쓴다.
노드 트리를 순회하는 방법: 반복문을 돌려 모든 노드를 순회한다.
노드 관계를 통해 탐색하는 방법: 이건 부모, 자식, 형제 노드 같은 관계를 이용해서 트리를 타고 다니는 거다.
일단 예시를 또 살펴보자
x.getElementsByTagName("title");
요소 안에 있는 title 태그들을 찾는 거다.
xmlDoc.getElementsByTagName("title");
xmlDoc 전체에서 title 태그를 다 가져오는 거다.
xmlDoc = xml.responseXML; 이렇게 넣어줌으로써 XML 전체 문서를 가져온다.
x = xmlDoc.getElementsByTagName("title");
y = x[2];
이렇게 사용하면 x에는 title 태그들로 이루어진 노드 리스트가 들어간다.
x의 세 번째 title 요소에 접근하여 y에 그 값을 넣는다.
또 다른 예제 코드를 살펴보자
function myFunction(xml) {
var x, i, txt, xmlDoc;
xmlDoc = xml.responseXML;
txt = "";
x = xmlDoc.getElementsByTagName("title");
for (i = 0; i < x.length; i++) {
txt += x[i].childNodes[0].nodeValue + "<br>";
}
document.getElementById("demo").innerHTML = txt;
}
책 제목을 가져오는 코든데 보면 나는 childNodes[0].nodeValue 이 부분이 이해가 안갔다.
근데 알고보니 <title lang="en">Everyday Italian</title> 이게
태그 안의 텍스트도 노드로 취급하기 때문이었다.
childNodes 자체는 <title lang="en">Everyday Italian</title>이거고
[0]을 넣음으로써 텍스트 노드를 가져온거다.
다음은 이 부분 살펴보자
function myFunction(xml) {
var x, i, xmlDoc, txt;
xmlDoc = xml.responseXML;
txt = "";
x = xmlDoc.documentElement.childNodes;
for (i = 0; i < x.length; i++) {
if (x[i].nodeType == 1) {
txt += x[i].nodeName + "<br>";
}
}
document.getElementById("demo").innerHTML = txt;
}
이 코드에서 nodeType == 1이 도대체 뭘까?
이건 노드 타입이 요소나 태그라는 것을 나타낸다.
만약 저것을 안넣었으면 텍스트 노드들도 반복문으로 출력하느라 바쁠 것이다.
다음을 살펴보자
function myFunction(xml) {
var xmlDoc = xml.responseXML;
var x = xmlDoc.getElementsByTagName("title")[0].childNodes[0];
document.getElementById("demo").innerHTML = x.nodeValue;
}
여기에 x.nodeValue 를 왜 쓸까?
분명 텍스트 노드가 들어가니 x만 써도 될 것 같은데 말이다.
근데 중요한 것은 텍스트 노드가 들어간다는 것이다.
어쨌든 얘도 노드이다.. 텍스트가 아니라.. 그렇기 때문에 nodeValue를 통해 텍스트를 끄집어낸다.
또 다음을 살펴보자
function myFunction(xml) {
var xmlDoc = xml.responseXML;
var x;
x = xmlDoc.getElementsByTagName("title")[0].childNodes[0];
document.getElementById("demo1").innerHTML = x.nodeValue;
x.nodeValue = "Easy Cooking";
x = xmlDoc.getElementsByTagName("title")[0].childNodes[0];
document.getElementById("demo2").innerHTML = x.nodeValue;
}
이거의 결과는 기존 노드값이 Easy Cooking로 바뀐다.
노드의 값이 바뀌는 것은 즉시 적용된다. 마치 포인터처럼
다음을 또 살펴보자
function myFunction(xml) {
var xmlDoc = xml.responseXML;
var x = get_firstChild(xmlDoc.getElementsByTagName("book")[0]);
document.getElementById("demo").innerHTML = x.nodeName;
}
//check if the first node is an element node
function get_firstChild(n) {
var y = n.firstChild;
while (y.nodeType != 1) {
y = y.nextSibling;
}
return y;
}
이건 0번째 book의 첫 아들을 찾는건데 firstChild, nextSibling 이들을 사용한다는 것 기억해두면 좋을 것 같고
while의 조건을 통해 요소 노드를 찾아 반환한다는 것 알아두자.
그럼 이제 노드에 접근해서 지우는 법을 알아보자
노드는 다음과 같이 지울 수 있다.
x.parentNode.removeChild(x);
이거는 x의 부모노드로 가서 자식을 지우는건데, 자기 자신을 지우는거나 마찬가지인 코드다.
DOM 트리 구조상 노드는 항상 부모 노드를 통해서만 제거될 수 있기 때문에.. 이렇게 하는거다.
아무튼 이 리무브칠드를 이용해서
x = xmlDoc.getElementsByTagName("title")[0];
y = x.childNodes[0];
x.removeChild(y);
이렇게 텍스트 노드도 지울 수 있다.
function myFunction(xml) {
var xmlDoc = xml.responseXML;
var x = xmlDoc.getElementsByTagName("book");
document.getElementById("demo").innerHTML =
x[0].getAttribute('category') + "<br>";
x[0].removeAttribute('category');
document.getElementById("demo").innerHTML +=
x[0].getAttribute('category');
}
이것처럼 attribute도 지울 수 있다.
category라는 어트리뷰트를 지우는거다.