[웹 서비스 개발] XML DOM - (1)

김광일·2024년 10월 14일

웹 서비스 개발

목록 보기
20/45
post-thumbnail

1. XML DOM

[1] XML DOM이란?

: XML DOM(문서 객체 모델, Document Object Model)은 XML 문서를 조작하기 위한 표준화된 방식이다.

  • 이를 통해 XML 요소에 접근하고, 변경하거나, 추가 및 삭제할 수 있다.

1) 특징

  1. 표준 객체 모델 : XML 문서를 트리 구조로 표현하여, 문서 내의 모든 요소를 '객체'로 다룰 수 있다.
  2. 표준 프로그래밍 인터페이스 : 다양한 프로그래밍 언어에서 XML 요소를 다루는 방법을 표준화하여, 특정 언어에 상관없이 동일한 방식으로 XML을 처리할 수 있다.
  3. 플랫폼 및 언어 독립적 : XML DOM은 특정 운영 체제나 프로그래밍 언어에 종속되지 않으며, 어디서나 활용할 수 있다.
  4. W3C 표준 : 세계 웹 표준 기구인 W3C(World Wide Web Consortium)에 의해 표준으로 채택된 방식이다.

[2] 간단한 예시

1) 예시

<p id="demo"></p>

<script>
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
            myFunction(this);
        }
    };
    xhttp.open("GET", "books.xml", true);
    xhttp.send();

    function myFunction(xml) {
        var xmlDoc = xml.responseXML;
        document.getElementById("demo").innerHTML 
        = xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;
    }
</script>
  • getElementsByTagName("title")[0]
    : XML에서 첫 번째 <title> 요소를 선택.
  • childNodes[0]
    : 그 <title> 요소의 첫 번째 자식 노드(텍스트 노드)를 선택.
  • nodeValue
    : 그 자식 노드의 텍스트 값(실제 제목 텍스트)을 가져옴.

[3] XML DOM peroperties

0) XML 예시

<library>
    <book id="1">
        <title>XML Basics</title>
        <author>John Doe</author>
    </book>
    <book id="2">
        <title>Advanced XML</title>
        <author>Jane Smith</author>
    </book>
</library>

1) x.nodeName

  • nodeName은 특정 노드의 이름을 반환한다.

코드 예시:

var x = xmlDoc.getElementsByTagName("title")[0];
console.log(x.nodeName);  // "title"
  • 설명: 첫 번째 <title> 노드의 이름을 출력한다.

2) x.nodeValue

  • nodeValue는 노드의 값을 반환한다. 요소 노드에선 null이지만, 텍스트 노드에서 텍스트 값을 가져온다.

코드 예시:

var x = xmlDoc.getElementsByTagName("title")[0].childNodes[0];  // 텍스트 노드
console.log(x.nodeValue);  // "XML Basics"
  • 설명: 첫 번째 <title> 요소 안에 있는 텍스트 값인 "XML Basics"을 반환합니다.

3) x.parentNode

  • parentNode는 현재 노드의 부모 노드를 반환합니다.

코드 예시:

var x = xmlDoc.getElementsByTagName("title")[0];
console.log(x.parentNode.nodeName);  // "book"
  • 설명: 첫 번째 <title> 노드의 부모는 <book> 노드이므로 "book"을 반환합니다.

4) x.childNodes

  • childNodes는 자식 노드를 배열처럼 반환합니다. 텍스트 노드와 같은 노드들도 포함됩니다.

코드 예시:

var x = xmlDoc.getElementsByTagName("book")[0];
console.log(x.childNodes[1].nodeName);  // "title"
console.log(x.childNodes[1].childNodes[0].nodeValue);  // "XML Basics"
  • 설명: 첫 번째 <book> 노드의 두 번째 자식 노드는 <title>, 그 안의 첫 번째 자식 노드는 "XML Basics"라는 텍스트 값을 가집니다.

5) x.attributes

  • attributes는 요소 노드의 속성을 배열처럼 반환합니다.

코드 예시:

var x = xmlDoc.getElementsByTagName("book")[0];
console.log(x.attributes[0].name);  // "id"
console.log(x.attributes[0].value); // "1"
  • 설명: 첫 번째 <book> 요소의 첫 번째 속성은 "id"이며, 그 값은 "1"입니다.

[4] XML DOM Methods

  1. x.getElementsByTagName(name)
  • 지정된 태그 이름을 가진 모든 자식 요소 노드를 검색하여 NodeList 형태로 반환한다.
  • 전체 XML 문서나 특정 요소 내에서 특정 태그 이름을 찾을 때 유용하다.
  • 예시: document.getElementsByTagName("title")은 XML 문서에서 모든 <title> 요소를 반환한다.
  1. x.appendChild(node)
  • 지정된 node를 현재 노드의 자식으로 추가한다.
  • 새로운 자식 노드를 기존 노드에 추가할 때 사용하며, 추가된 노드는 항상 마지막 자식으로 배치된다.
  • 예시: <book></book>newNodeappendChild 하면 <book><newNode></newNode></book> 형태가 된다.
  1. x.removeChild(node)
  • 현재 노드에서 지정된 node 자식 노드를 제거합니다.
  • 자식 노드를 삭제할 때 사용하며, 성공적으로 삭제되면 제거된 노드를 반환합니다.
  • 예시: <book><title>Book</title></book>에서 <title> 노드를 removeChild 하면 <book></book>이 됩니다.

[5] XML DOM에서의 모든 것은 'node'

: XML DOM에서는 XML 문서의 모든 것이 노드로 간주된다.

  1. 문서 전체는 문서 노드 (Document Node):
  • XML 문서 전체는 하나의 문서 노드로 시작합니다. 이는 XML 트리 구조의 최상위 노드입니다.
  1. 각 XML 요소는 요소 노드 (Element Node):
  • XML의 각 태그(예: <book>, <title>)는 요소 노드로 취급됩니다. 이 노드는 XML 구조의 핵심 구성 요소입니다.
  1. XML 요소 안의 텍스트는 텍스트 노드 (Text Node):
  • XML 요소 내의 텍스트(예: <title>XML Basics</title>에서 "XML Basics")는 텍스트 노드로 분리되어 저장됩니다.
  1. 각 속성은 속성 노드 (Attribute Node):
  • XML 요소의 속성(예: <book id="1">에서 id="1")은 속성 노드로 취급됩니다. 속성 노드는 요소 노드의 일부지만 자식 노드는 아닙니다.
  1. 주석은 주석 노드 (Comment Node):
  • XML 문서 내의 주석(예: <!-- This is a comment -->)은 주석 노드로 간주됩니다. 주석은 데이터 처리에 영향을 미치지 않지만 문서에 기록된 정보를 설명하는 데 사용됩니다.

[6] 텍스트는 항상 텍스트 노드에 저장한다.

: DOM 처리에서 흔히 발생하는 오류는 요소 노드에 텍스트가 포함될 것으로 예상하는 것이다.

  • 그러나 요소 노드의 텍스트는 텍스트 노드에 저장된다.
  • 예를 들어, <year>2005</year>에서 요소 노드 <year>는 값이 "2005"인 텍스트 노드를 보유한다.
  • 즉, "2005"<year> 요소의 값이 아니라, 텍스트 노드의 값이다다!

[7] XML DOM 노드 트리

XML DOM Tree Structure

: XML DOM은 XML 문서를 트리 구조로 나타낸다. 이 구조를 노드 트리라고 부른다.

  • 모든 노드는 이 트리를 통해 액세스할 수 있다.
    • 노드의 내용을 수정하거나 삭제할 수 있으며, 새로운 요소를 만들 수도 있다.
  • 노드 트리노드 집합과 노드 간의 연결을 보여준다.

[8] 노드 엑세스

: 세 가지 방법으로 노드에 엑세스할 수 있다.

  1. getElementByTagName() 메소드를 사용한다.
  2. node tree를 번복(travers)한다.
  3. 노드 관계를 사용하여 노드 트리를 탐색한다.

2. 본격적인 DOM 관련 내용

[1] DOM Node List

: getElementsByTagName() 메소드는 node list를 반환한다.

  • node list는 node의 배열이 담겨 있다.

1) 형태

x = xmlDoc.getElementsByTagName("title");

2) 특징

// 세 번째 `<title>`에 액세스
y = x[2];

: x의 <title> 요소는 색인 번호로 액세스할 수 있다.

3) 예시

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;
}

: title 태그들을 싹 찾고, 해당 태그의 nodeValue를 추가하여 id가 demo인 태그에 삽입하는 구조.

[2] documentElement, nodeType

1) 예시

function myFunction(xml) {
    var xmlDoc = xml.responseXML;
    document.getElementById("demo").innerHTML =
        xmlDoc.documentElement.nodeName + "<br>" +
        xmlDoc.documentElement.nodeType;
}

: 이 함수는 XML 파일에서 특정 정보를 가져와서 HTML 요소에 표시하는 역할을 한다.

2) documentElement.nodeName

  • XML 문서의 루트 요소의 이름을 반환한다.
  • 예를 들어, XML 문서가 <library>...</library>라는 구조라면, nodeName"library"가 된다.

2) documentElement.nodeType

  • 이 부분은 해당 노드의 유형을 반환한다.
  • 노드 유형은 숫자로 반환되며, 각 숫자는 노드의 종류를 나타낸다
    • . 예를 들어, 루트 요소 노드는 1 (요소 노드)이다.

3) nodeType에 대한 설명

: nodeType은 각 XML DOM 노드의 유형을 나타내는 숫자 값이다.

  1. 요소 노드 (Element Node) - 1
  • XML의 요소(예: <book>, <title>)는 1로 표현된다.
  1. 속성 노드 (Attribute Node) - 2
  • XML 요소의 속성(예: <book id="1">)은 2로 표현된다.
  1. 텍스트 노드 (Text Node) - 3
  • 요소 안에 있는 텍스트(예: <title>XML Basics</title>에서 "XML Basics")는 3으로 표현된다.
  1. 주석 노드 (Comment Node) - 8
  • 주석(예: <!-- This is a comment -->)은 8로 표현된다.
  1. 문서 노드 (Document Node) - 9
  • XML 문서 전체는 9로 표현된다.

[3] childNode의 숨겨진 비밀

1) 예시 코드

function myFunction(xml) {
    var x, i, xmlDoc, txt;
    xmlDoc = xml.responseXML;
    txt = "";
    x = xmlDoc.documentElement.childNodes;
    for (i = 0; i < x.length; i++) {
        txt += x[i].nodeName + "<br>";
    }
    document.getElementById("demo").innerHTML = txt;
}

2) 결과

#text
book
#text
book
#text
book
#text
book
#text

3) 왜 #text가 나오는가?

  • childNodes모든 자식 노드를 반환하며, 여기에는 텍스트 노드도 포함됩니다.
  • XML 요소 사이의 공백이나 줄바꿈이 텍스트 노드로 처리되어 #text가 나타납니다.

4) 해결 방법

  • 요소 노드만 출력하려면 nodeType을 사용해 필터링하면 됩니다.
for (i = 0; i < x.length; i++) {
    if (x[i].nodeType === 1) { // 요소 노드만 출력
        txt += x[i].nodeName + "<br>";
    }
}

5) 수정 후 결과

book
book
book
book
book

이렇게 하면 공백 텍스트 노드가 출력되지 않고, <book> 요소들만 출력됩니다.

[4] nextSibling

1) 예시 코드

function myFunction(xml) {
    var x, y, i, xlen, xmlDoc, txt;
    xmlDoc = xml.responseXML;
    x = xmlDoc.getElementsByTagName("book")[0]; // 첫 번째 <book> 요소
    xlen = x.childNodes.length; // 자식 노드 수
    y = x.firstChild; // 첫 번째 자식 노드
    txt = "";
    
    for (i = 0; i < xlen; i++) {
        if (y.nodeType == 1) { // 요소 노드만 확인
            txt += i + " " + y.nodeName + "<br>"; // 인덱스와 노드 이름 저장
        }
        y = y.nextSibling; // 다음 형제 노드로 이동
    }
    document.getElementById("demo").innerHTML = txt; // 결과 출력
}

2) 주요 개념

  • nextSibling: 현재 노드의 다음 형제 노드를 참조한다
    • nextSibling은 현재 노드의 다음 형제 노드를 참조하는 프로퍼티이다.
    • 즉, 현재 노드와 같은 부모를 가지며, 바로 다음에 위치한 노드를 가리킵니다.
  • 요소 노드 확인: y.nodeType == 1을 통해 요소 노드만 필터링하여 출력한다.

[5] getAttribute("속성이름");

1) 예시

function myFunction(xml) {
    var x, y, i, xlen, xmlDoc, txt;
    xmlDoc = xml.responseXML;
    x = xmlDoc.getElementsByTagName("book")[0];
    xlen = x.childNodes.length;
    y = x.firstChild;
    txt = "";
    for (i = 0; i < xlen; i++) {
        console.log(y);
        if(y.nodeType == 1)
            txt += i + " Node name: " + y.nodeName + "; Attri. value : " + y.getAttribute("lang")+ "<br>";
        y = y.nextSibling;
    }
    document.getElementById("demo").innerHTML = txt;
}
  • y.getAttribute("lang") : lang이라는 속성을 가진 요소의 value 값을 Return한다.
    • 없으면 null을 Return한다.

[6] nodeName, nodeValue

1. nodeName

  • 정의: 노드의 이름을 반환하는 속성.
  • 특징:
    • 읽기 전용 속성.
    • element 노드: 태그 이름과 동일.
    • attribute 노드: 속성 이름.
    • text 노드: 항상 #text.
    • document 노드: 항상 #document.
  • 예시:
    • Element Node: <title>nodeName은 "title".
    • Attribute Node: <book category="COOKING">에서 category 속성의 nodeName은 "category".
    • Text Node: <year>2005</year>의 텍스트 노드에서 nodeName#text.
    • Document Node: XML 문서의 루트에서 nodeName#document.

2. nodeValue

  • 정의: 노드의 값을 반환하는 속성.
  • 특징:
    • element 노드: 값이 정의되지 않음.
    • text 노드: 텍스트 자체.
    • attribute 노드: 속성 값.
  • 예시:
    • Element Node: <title>nodeValue는 정의되지 않음.
    • Attribute Node: <book category="COOKING">에서 category 속성의 nodeValue는 "COOKING".
    • Text Node: <year>2005</year>의 텍스트 노드에서 nodeValue는 "2005".
    • Document Node: XML 문서의 nodeValue는 정의되지 않음.

이렇게 각 노드 유형에 대한 설명과 예시를 추가하여 내용을 간결하게 정리했습니다.

[7] nodeValue를 변경

: 텍스트 노드의 값은 nodeValue를 통해 직접 변경할 수 있다. 이를 통해 XML 문서의 특정 내용을 동적으로 수정할 수 있는 강력한 기능을 제공한다.

1) 예시

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;
}
  1. 텍스트 노드 접근:
x = xmlDoc.getElementsByTagName("title")[0].childNodes[0];
  • 이 코드에서 x는 첫 번째 <title> 요소의 첫 번째 자식인 텍스트 노드에 접근한다. 이 텍스트 노드는 초기값을 가진다.
  1. 초기 텍스트 값 출력:
document.getElementById("demo1").innerHTML = x.nodeValue;
  • 초기 텍스트 값(예: "Everyday Italian")을 demo1 요소에 출력한다.
  1. 텍스트 노드 값 변경:
x.nodeValue = "Easy Cooking";
  • 이 코드가 핵심이다. x로 참조된 텍스트 노드의 값을 "Easy Cooking"으로 변경한다. nodeValue 속성은 텍스트 노드의 내용을 직접 수정할 수 있게 해준다.
  1. 변경된 텍스트 값 출력:
document.getElementById("demo2").innerHTML = x.nodeValue;
  • 수정된 텍스트 값("Easy Cooking")을 demo2 요소에 출력한다.

[8] getNamedItem

1) 예시

function myFunction(xml) {
    var x, txt,xmlDoc;
    xmlDoc = xml.responseXML;
    x = xmlDoc.getElementsByTagName("book")[0].attributes;
    console.log(x);
    txt = x.getNamedItem("category").nodeValue + "<br>" + x.length;
    document.getElementById("demo").innerHTML = txt;
}
  1. XML 문서 접근:
xmlDoc = xml.responseXML;
  • xml.responseXML을 통해 XML 문서의 DOM 객체를 가져옵니다.
  1. 첫 번째 <book> 요소의 속성 접근:
x = xmlDoc.getElementsByTagName("book")[0].attributes;
  • 이 코드는 첫 번째 <book> 요소의 모든 속성(attribute)을 가져옵니다. x는 속성 목록을 포함하는 NamedNodeMap 객체입니다.
  1. 속성 값과 속성 수 출력:
txt = x.getNamedItem("category").nodeValue + "<br>" + x.length;
  • getNamedItem("category") 메소드를 사용하여 "category"라는 이름의 속성을 가져옵니다.
  • .nodeValue를 통해 해당 속성의 값을 출력합니다.
  • x.length는 속성의 총 개수를 반환합니다.
  1. 결과 출력:
document.getElementById("demo").innerHTML = txt;
  • 최종적으로 txt 변수를 HTML 요소에 출력하여 "category" 속성의 값과 총 속성 개수를 표시합니다.

2) getNamedItem 메소드

  • 용도: getNamedItem(name) 메소드는 특정 이름의 속성을 검색하고, 해당 속성을 Attr 노드로 반환한다.
  • 사용 예:
    • x.getNamedItem("category")는 "category"라는 속성의 정보를 가져온다. 만약 "category" 속성이 존재한다면, 해당 속성의 값을 nodeValue로 쉽게 접근할 수 있다.
  • 반환값: 만약 해당 속성이 존재하지 않으면 null을 반환한다.

[9] while 구문을 통해 찾는 예시

1) 코드

  1. 전체
      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) {
            console.log(n);
            var y = n.firstChild;
            while (y.nodeType != 1) {
                y = y.nextSibling;
            }
            console.log(y);
            return y;
        }
  1. 특정 구문
while (y.nodeType != 1) {
  y = y.nextSibling;
}

2) 코드의 필요 구문 설명

  • 목적: 첫 번째 자식 노드가 요소 노드인지 확인하기 위해 사용된다.
  • 동작:
    • y.nodeType != 1일 경우, 즉 비요소 노드(예: 텍스트 노드)일 때 다음 형제 노드로 이동한다.
    • 반복하여 첫 번째 요소 노드가 나올 때까지 계속 진행한다.
  • 결과: 최종적으로 y는 첫 번째 요소 노드를 가리키게 된다.

profile
안녕하세요, 사용자들의 문제 해결을 중심으로 하는 프론트엔드 개발자입니다. 티스토리로 전환했어요 : https://pangil-log.tistory.com

0개의 댓글