본문 바로가기
Programming/Web

DOM 노드트리 순회하기

by hyunipad 2021. 1. 4.
반응형

안녕하세요 혀니입니다.

개발 공부를 시작하고, Javascript, JQuery를 많이 사용했었지만, 회사에 입사하고 배우면서 그것들이 DOM(Document Object Model)이라는 것을 알았습니다.

보통 document.getElementsByTagName() 메서드를 사용하여 태그 네임을 가져오게 됩니다. 하지만 이번 포스팅에선 getElementsByTagName()을 쓰지 않고 태그 네임을 가져오도록 하겠습니다.

 

01. DOM의 구조

 

선택자를 사용하지 않고, 노드에 접근하기 위해선 DOM이 어떤 구조로 되어 있는지 알아야 합니다. DOM은 아래의 계층구조로 이루어져 있습니다.

DOM 트리구조

어디서 많이 보지 않았나요? 네 바로 트리구조입니다.

그렇다면 트리순회를 통해 자식 노드부터 루트 노드까지 접근할 수 있지 않을까요?

 

02. 트리순회

 

트리 순회에는 3가지의 방법이 있습니다.

  • 전위 순회 : root -> left -> right
  • 중위 순회 : left -> root -> right
  • 후위 순회 : left -> right -> root

비전공자라서 알고리즘을 잘 모르긴 하지만, 트리 순회를 할 때는 재귀 호출을 사용하여 자식 노드에 접근할 수 있습니다.

노드에 접근 후 4가지 항목에 대해 비교하여 일치하는 노드의 개수를 파악하는 알고리즘입니다.

  • Id
  • TagName
  • Attribute name
  • Attribute value
<form action="search2" enctype="application/x-www-form-urlencoded" method="get">
            <div class="a"><label>Id</label><input class="input1" id="id" name="id" type="text"/></div>
            <div class="a"><label>노드명</label><input class="input2" id="node_name" name="node_name" type="text"/></div>
            <div class="a"><label>속성명</label><input class="input2" id="att_name" name="att_name" type="text"/></div>
            <div class="a"><label>속성값</label><input class="input2" id="att_value" name="att_value" type="text"/></div>
            <div class="b">
                <input class="input3" onclick="search1()" type="button" value="검색(JavaScript)"/> //javascript 검색방식
                <input class="input3" type="submit" value="검색(Java)"/> //  java 검색 방식(서버단)
                <input class="input3" type="button" value="검색(JQuery)" id="search3"/> // JQuery 검색 방식
            </div>
</form>

 

<script type="text/javascript">
//<![CDATA[
    function search1() {
        
        var id = document.getElementById('id').value;
        var node_name = document.getElementById('node_name').value;
        var att_name = document.getElementById('att_name').value;
        var att_value = document.getElementById('att_value').value;
        
        var count = checkDOM(document.getElementById('main'), id, node_name, att_name, att_value, 0);    
        document.getElementById("c").textContent = "총   " + count + "개입니다.";
    }
        
    function checkDOM(node, id, node_name, att_name, att_value, count){
        
        for(var i = 0 ; i < node.childNodes.length; i++){ // checkDOM의 파라미터로 받은 노드의 자식노드로 재귀함수 호출함.            
            depth = checkDOM(node.childNodes[i], id, node_name, att_name, att_value, count);            
        }
        // 더이상 자식노드가 없으면 노드 검사 실행
        // 자식노드 부터 카운트를 리턴해주면서 갯수 세어감.
        if(node.nodeType != 3){ // 노드타입 비교는 => 텍스트노드를 제외하기 위함, 텍스트노드에는 속성이 없어 예외발생함.
            if(!isEmpty(id)){ // id 안비어져있으면
                if(node.id != id){ // id 비교 => 일치하지 않으면 
                    return count; 
                }
            }
        
            if(!isEmpty(node_name)){ // 태그네임 안 비어져있으면
                if(node.nodeName != node_name){ // 태그네임 비교
                    return count; 
                }
            }
        
            if(!isEmpty(att_name)){ // 속성이름 안비어져있으면
                if(!(node.hasAttribute(att_name))){ // 속성 가지고 있지 않으면
                    return count;
                }    
            }
            
            if(!isEmpty(att_value)){ // 속성값 안 비어져있으면
                if(node.getAttribute(att_name) != att_value){ // 속성값 비교
                    return count;
                }
            }            
            count++;
        }
        return count;
    }
 
    function isEmpty(value) {
        if(typeof value == "undefined" || value == null || value == ""){
            return true;
        }else{
            return false;
        }
    }    
//]]>
</script>
반응형

댓글