컴공지식/웹

노드에 접근하는 법

개강한 공대생 2024. 10. 14. 22:02

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라는 어트리뷰트를 지우는거다.