문서객체모델(Document Object Model, DOM)은 HTML과 XML 문서에 대한 프로그래밍 인터페이스
문서에 대한 구조적 정보를 제공하고 문서 구조나 외양 및 내용을 프로그램에서 접근할수 있는 방법 제공
DOM 노드의 유형
1. Node.ELEMENT_NODE는 엘리먼트 노드 유형에 대한 상수
2. Node.ATTRIBUTE_NODE는 애트리뷰트 노드 유형에 대한 상수
3. Node.TEXT_NODE는 텍스트 노드 유형에 대한 상수
4. Node.DOCUMENT_NODE는 문서 노드 유형에 대한 상수
다른 노드 유형들도 많이 있지만 주로 이 네가지 유형을 다루기 때문에 예시 하지 않는다.
nodeType 속성
DOM 노드 유형에 대해 상수로 정의 되어 있으므로 모든 노드에서 사용할수 있는 nodeType 속성을
사용하여 위 상수와 비교 함으로서 노드 타입을 알수 있다.
Internet Explorer는 자바스크립트에서 Node 상수를 사용할때 에러를 보고 한다.
Internet Explorer 7.0부터 이러한 문제를 정정했다 하지만 보편적으로 사용하는 6.0에서는 정상작동 하지 않는다.
따라서 Node 사용을 피해야 할것이다. 그냥 이런 것이 있다고만 알아 두도록 하자.
DOM
- Dom(Document Object Model) 노드 타입 2011.04.18
- Java와 XML 6장 Advanced DOM 2009.02.25
- Java와 XML 5장 DOM 2009.02.25
- DOM 관련 파서들 (DOM, JDOM, SAX, JAX, JAXP, StAX) 2009.02.25
Dom(Document Object Model) 노드 타입
2011. 4. 18. 17:27
반응형
Java와 XML 6장 Advanced DOM
2009. 2. 25. 15:19
반응형
출처: http://kr.blog.yahoo.com/kwon37xi/folder/3381246.html
- DOM은 XML을 생성하고 변경할 수 있다.
XML DOM 트리의 생성과 변경
- 새로운 XML을 생성하기 위해서는 org.w3c.dom.DOMImplementation을 구현한 클래스를 사용해야한다.
- Xerces의 DOMImplementation구현 : org.apache.xerces.dom.DOMImplementationImpl
- 생성 예
DOMImplementation domImpl = new DOMImplementationImpl(); Document doc = domImpl.createDocument(null, "rootElement", null);
- Document 객체 생성시 파서의 Document 구현 클래스를 사용하면 DocType 이 생성되지 않는다. DOMImplementation 을 사용해서 새로운 XML DOM 트리를 생성해야 한다.
- DOMImplementation.createDocument(1,2,3);
- 첫번째 인자 : 문서의 루트 요소를 위한 네임스페이스
- 두번째 인자 : 루토 요소
- 세번째 인자 : DocType 클래스의 인스턴스.
- 첫번째 인자 : 문서의 루트 요소를 위한 네임스페이스
- DocType이 필요할 경우 DOMImplementation.createDocType() 사용.
- 변경 예
Element root = doc.getDocumentEelment(); root.setAttribute("id", id); // id 속성의 추가 Element nameElement = doc.createElement("name"); Text nameText = doc.createTextNode("내용"); nameElement.appendChild(nameText); //name 요소에 텍스트 값 추가 root.appendChild(nameElement); // rootElement 요소에 name 요소 추가
- 모든 노드의 생성은 Document 객체의 create* 메소드를 통해서 이뤄진다.
- "appendChild()"는 자식 노드를 추가한다.
네임스페이스
- DOM Level 2는 네임스페이스를 지원한다.
- 네임스페이스를 위해 Node 인터페이스는 "getPrefix()"와 "getNamespaceURI()" 메소드를 제공한다.
- Document.createElementNS() 네임스페이스를 지원하는 요소 추가.
- 네임스페이스를 인식하는 각 메소드의 첫번째 인자는 "네임스페이스 URI"이고, 두번째 인자는 요소와 속성등의 QName이다. QName은 "ora:copyright" 와 같은 형태를 띈다.
- "ora:copyright" 요소에서 getPrefix() : "ora" 리턴
- 네임스페이스에 속하지 않는 요소에서 getPrefix() : null 리턴
- 네임스페이스를 지정했을 때는 루트 요소에 xmlns 속성을 지정해야 한다.
DOM Level 2 - 순회(Traverse)
- DOM 트리를 순회하는 기능을 제공한다.
- "org.w3c.dom.traversal.DocumentTraversal" 인터페이스를 이용한다.
- 일반적인 파서의 Document 구현 클래스는 DocumentTraversal 도 함께 구현한다.
- NodeIterator 예
NodeList descriptionElements = root.getElementsByTagNameNS(docNS, "description"); Element description = (Element)descriptionElements.item(0); // NodeIterator를 구한다. NodeIterator i = ((DocumentTraversal)doc) .createNodeIterator(description, NodeFilter.SHOW_ALL, new FormattingNodeFilter(), true); Node n; while ((n = i.nextNode()) != null) { System.out.println("Search phrase found: '" + n.getNod eVal ue() + "'"); }
- createNodeIterator(1, 2, 3, 4)
- 첫번째 인자 : 순회할 노드 요소
- 두번째 인자 : 상수 필터
- NodeFilter.SHOW_ALL : 모든 노드를 포함하여 순회
- NodeFilter.SHOW_ELEMENT : 요소만 순회
- NodeFilter.SHOW_TEXT : 텍스트 노드만 순회
- NodeFilter.SHOW_ALL : 모든 노드를 포함하여 순회
- 세번째 인자 : NodeFilter 구현 객체
- 네번째 인자 : 엔티티 참조의 실제값을 분석할 것인가?
- 두번째와 세번째 인자가 함께 나올 경우 두번째 인자 필터를 우선적용하고 그 결과를 다시 세번째 인자로 필터링한다.
- 첫번째 인자 : 순회할 노드 요소
- NodeFilter
- public short acceptNode(Node n); 을 이용해서 순회할 노드인지 여부를 결정한다.
- 리턴값 NodeFilter.FILTER_SKIP : 필터로 들어온 노드는 건너 뛰고 그 자식노드를 계속 탐색
- 리턴값 NodeFilter.FILTER_REJECT : 필터로 들어온 노드와 그 자식 모두 건너 뜀
- 리턴값 NodeFilter.FILTER_ACCEPT : 필터로 들어온 노드 사용
- 리턴값 NodeFilter.FILTER_SKIP : 필터로 들어온 노드는 건너 뛰고 그 자식노드를 계속 탐색
- 노드 필터 예
class FormattingNodeFilter implements NodeFilter { public short acceptNode(Node n) { if (n.getNodeType() == Node.TEXT_NODE) { Node parent = n.getParentNode(); if ((parent.getNodeName().equalsIgnoreCase("b")) || (parent.getNodeName().equalsIgnoreCase("i"))) { return FILTER_ACCEPT; } } return FILTER_SKIP; } }
- public short acceptNode(Node n); 을 이용해서 순회할 노드인지 여부를 결정한다.
- TreeWalker
트리 뷰를 얻는다. 필터를 이용해 특정한 요소 등만 가진 트리를 생성해낸다.
범위(Range)
알 수 없는 DOM 구조에 새로운 컨텐트를 추가하거나 또는 컨텐트를 삭제, 복사, 추출해야 할 경우에 범위 모듈을 사용한다.다른 문서의 노드를 현재 문서에 append하려면 importNode를 사용한다.
Element otherDocElement = otherDoc.getDocumentElement(); Element thisDocElement = thisDoc.getDocumentElement(); // 대상 문서에 노드 임포트 Element readyToUseElement = (Element)thisDoc.importNode(otherDocElement); // 아무문제없이 노드 추가 thisDocElement.appendChild(readyToUseElement);
Java와 XML 5장 DOM
2009. 2. 25. 15:17
반응형
출처: http://kr.blog.yahoo.com/kwon37xi/folder/3381246.html
DOM(Document Object Model)은 모든 프로그래밍 언어와 개발 도구에서 사용하는 문서의 컨텐트 모델을 표현하기 위해 설계되었다. 각 언어별로 바인딩이 존재한다.
이 점은 장점이 될 수도 있지만, JAVA 고유의 편리한 기능을 사용할 수 없어, 단점으로 작용하기도 한다. JAVA 고유의 기능을 사용한 JDOM이 DOM보다 훨씬 편리하다.
DOM(Document Object Model)은 모든 프로그래밍 언어와 개발 도구에서 사용하는 문서의 컨텐트 모델을 표현하기 위해 설계되었다. 각 언어별로 바인딩이 존재한다.
이 점은 장점이 될 수도 있지만, JAVA 고유의 편리한 기능을 사용할 수 없어, 단점으로 작용하기도 한다. JAVA 고유의 기능을 사용한 JDOM이 DOM보다 훨씬 편리하다.
- DOM은 모든 면에서 트리 모델이다.
- DOM은 XML문서 전체를 메모리에 저장하여 표현한다.
- 각 트리는 org.w3c.dom.Node 인턴페이스를 기반으로 한다. 요소, 속성, 텍스트, PI, 주석 등 모든 것이 Node로 표현된다.
- 요소의 텍스트도 하나의 트리로 간주된다. 그러므로 Element 노드의 텍스트를 구할 때 "getText()"와 같은 방식으로 구할 수 없고, 요소의 Text 자식 노드들을 구한뒤, 거기서 값을 가져와야한다.
SAX의 장/단점
- SAX는 순차적이라 XML문서의 요소를 무작위로 접근할 수 없다.
- 형제 요소를 처리하기 어렵다.
- 메모리를 훨씬 적게 사용한다.
XML 파싱 : Xerces 기준
- DOM에서는 문서를 완전히 분석하여 트리 구조가 생성되어야 XML 문서의 데이터를 사용할 수 있다.
- DOM에서 문서를 분석한 결과는 org.dom.w3c.dom.Document 객체로 표현된다.
- 다음과 같이 XML 문서를 파싱한다.
import org.apache.xerces.parsers.DOMParser; // 파서 import import org.w3c.dom.*; // DOM 인터페에스 import ... DOMParser parser = new DOMParser(); // Document 객체인 DOM 트리 구성 parser.parse("document.xml"); Document doc = parser.getDocument(); // DOM Document 객체 얻기
- import org.apache.xerces.parsers.DOMParser
- void parse(org.xml.sax.InputSource inputSource)
- void parse(java.lang.String systemId)
- void parse(org.xml.sax.InputSource inputSource)
Node
- DOM의 장점중의 하나는 XML을 표현하는(Document 객체를 포함한) 모든 DOM 객체가 DOM의 Node인터페이스를 상속한다는 점이다.
- Node.getNodeType() : 현재 노드의 타입(요소, 속성, PI 등등..)을 가리킨다.
- Document.getDocumentElement() : 최상위 요소(Root Element) 노드
- Node.getNodeName() : 노드의 이름. Text 노드(요소의 값)의 경우 이 노드 이름은 의미가 없다.
- Node.getNodeValue() : 노드의 값. Element 노드의 경우 이 값은 의미가 없으며 자식 노드를 구해 그 중 Text노드의 값을 가져와야만 한다.
- Node.getChildNodes() : NodeList 인스턴스 반환. 자식 노드 목록.
- NamedNodeMap Node.getAttributes() : Element 노드의 경우에만 유효. 속성 목록을 반환한다.
- NodeList.item(int) : 자식 Node들을 순서대로 반환받는다.
DOCTYPE, PI 등의 처리
최상위 엘리먼트보다 상위에 오는 DOCTYPE과 PI(처리 지시어; Processing Instruction)등을 처리하려면 Document 노드 단에서 자식 노드들을 얻어야만 한다.다음과 같은 XML이 있을 때
이 상황에서 "child1" 노드 객체를 가져올 때
<root> <child1>hello</child1> <child2>hi~</chil2> </root>위 XML을 파싱하여 "root" 엘리먼트 Node 객체에서 getChildNodes()를 했을 경우에 주의할 점이 있다.
이 상황에서 "child1" 노드 객체를 가져올 때
DOMParser parser = new DOMParser(); parser.parse("test.xml"); Document doc = parser.getDocument(); Element root = doc.getDocumentElement(); NodeList children = root.getChildNodes(); // root 의 자식 노드 얻기 -- !! 요주의 부분!! Node child1Node = children.item(0); // child1 요소 얻기 Node textNode = child1Node.getChildNodes().item(0); // child1의 텍스트 얻기 System.out.println("child1 : " + textNode.getNodeValue());위와 같이 하면 제대로 값을 가져올 수 있을까?
답은 "가져올 수도 있고 못 가져올 수도 있으나, 십중팔구는 NullPointerException이 발생한다는 것이다."
NullPointerException이 발생한다면 그것은 textNode가 null이기 때문이다.
위와 같이 NodeList.item(int) 메소드를 사용할 경우에 root 요소와 child1 요소 사이의 공백이 Text 노드로서 읽힐 수도 있다. 이 경우 NodeList.item(0)가 리턴하는 노드는 child1 요소가 아니라 root요소의 Text 노드가 되는 것이다.
만약 root 요소와 child1요소 사이에 아무런 공백도 없거나 DTD 등으로 공백을 무시하도록 했다면 안 그럴 수도 있다.
NullPointerException이 발생한다면 그것은 textNode가 null이기 때문이다.
위와 같이 NodeList.item(int) 메소드를 사용할 경우에 root 요소와 child1 요소 사이의 공백이 Text 노드로서 읽힐 수도 있다. 이 경우 NodeList.item(0)가 리턴하는 노드는 child1 요소가 아니라 root요소의 Text 노드가 되는 것이다.
만약 root 요소와 child1요소 사이에 아무런 공백도 없거나 DTD 등으로 공백을 무시하도록 했다면 안 그럴 수도 있다.
그러므로 child1 요소를 명백하게 가져오려고 할 경우에는 root.getChildNodes()를 사용해서는 안된다. root 노드를 Element 객체로 캐스팅하고 Element.getElementsByTagName(String)으로 명백하게 가져와야 한다.
Element root = doc.getDocumentElement(); // 이 부분이 바뀌었다!! NodeList children = root.getElementsByTagName("child1"); // root 의 자식 노드 얻기 Node child1Node = children.item(0); // child1 요소 얻기 Node textNode = child1Node.getChildNodes().item(0); // child1의 텍스트 얻기 System.out.println("child1 : " + textNode.getNodeValue());
위와 같이 하면 children 객체에는 요소 이름이 "child1"인 요소만 남게 된다.
DOM 관련 파서들 (DOM, JDOM, SAX, JAX, JAXP, StAX)
2009. 2. 25. 14:27
반응형
본 문서는 http://cafe.naver.com/specialj.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=1336 을 참조
DOM 문서 객체 모델 [文書客體-, document object model] |
|
JDOM [Java Document Object Model] | ||
| ||
|
SAX [simple API for XML, simple application program interface for Extensible Markup Language] | ||
| ||
|
JAX [Java API for XML] | ||
| ||
|
자바 XML팩 [Java XML Pack] | ||
| ||
|
그외에 웹로직으로 알려진 BEA Systems의 스택스(StAX: Streaming API for Java)가 있다.