이 질문에 대한 일반적인 Q & A 지향 답변을 제공합니다.
질문에 대한 답변
왜 XML 파서가 필요합니까?
우리는 XML 파서가 필요하다. 우리는 애플리케이션에서 모든 것을 처음부터하고 싶지 않기 때문에, 매우 낮은 수준이지만 우리에게 매우 필요한 것을 수행하기 위해 "도우미"프로그램이나 라이브러리가 필요하다. 이러한 하위 수준이지만 필요한 것은 올바른 형식 확인, DTD 또는 스키마에 대한 문서 유효성 검사 (파서 유효성 검사 용), 문자 참조 확인, CDATA 섹션 이해 등을 포함합니다. XML 파서는 그러한 "도우미"프로그램 일 뿐이며 이러한 모든 작업을 수행 할 것입니다. XML 파서를 사용하면 이러한 복잡성으로부터 보호받을 수 있으며 파서에 의해 구현 된 API를 통해 높은 수준의 프로그래밍에만 집중할 수있어 프로그래밍 효율성을 얻을 수 있습니다.
SAX 또는 DOM 중 어느 것이 더 낫습니까?
SAX와 DOM 파서 모두 장단점이 있습니다. 어느 것이 더 나은지 응용 프로그램의 특성에 따라 달라집니다 (아래 몇 가지 질문을 참조하십시오).
어느 파서가 더 빠른 속도를 얻을 수 있습니까, DOM 또는 SAX 파서입니까?
SAX 파서는 더 빠른 속도를 얻을 수 있습니다.
트리 기반 API와 이벤트 기반 API의 차이점은 무엇입니까?
트리 기반 API는 트리 구조를 중심으로하기 때문에 문서 인터페이스, 노드 인터페이스, NodeList 인터페이스, 요소 인터페이스, Attr 인터페이스 등과 같은 트리의 컴포넌트 (DOM 문서)에 대한 인터페이스를 제공합니다. 그러나 이벤트 기반 API는 처리기에서 인터페이스를 제공합니다. 처리기 인터페이스에는 ContentHandler 인터페이스, DTDHandler 인터페이스, EntityResolver 인터페이스 및 ErrorHandler 인터페이스가 있습니다.
DOM 파서와 SAX 파서의 차이점은 무엇입니까?
DOM 파서와 SAX 파서는 다른 방식으로 작동합니다.
DOM 파서는 입력 문서에서 메모리에 트리 구조를 작성한 다음 클라이언트의 요청을 기다립니다. 그러나 SAX 파서는 내부 구조를 만들지 않습니다. 대신 입력 문서의 구성 요소 발생을 이벤트로 가져 와서 입력 문서를 읽을 때 읽은 내용을 클라이언트에 알려줍니다. ㅏ
DOM 파서는 클라이언트가 실제로 필요한 양에 관계없이 항상 전체 문서로 클라이언트 응용 프로그램을 제공합니다. 그러나 SAX 파서는 항상 주어진 시간에 문서 조각만으로 클라이언트 응용 프로그램을 제공합니다.
- DOM 파서를 사용하면 클라이언트 응용 프로그램의 메서드 호출은 명시 적이어야하며 일종의 체인을 형성해야합니다. 그러나 SAX를 사용하면 특정 이벤트가 발생할 때 "콜백"이라고하는 방식으로 일부 메서드 (일반적으로 cient에 의해 재정의 됨)가 자동으로 호출됩니다. 이러한 메소드는 클라이언트가 명시 적으로 호출 할 필요는 없지만 명시 적으로 호출 할 수는 있습니다.
어떤 파서가 좋은지 어떻게 결정합니까?
이상적으로 좋은 파서는 빠르고 (시간 효율적) 공간 효율적이며 기능이 풍부하고 사용하기 쉬워야합니다. 그러나 실제로 주요 파서 중 어느 것도 이러한 기능을 동시에 가지고 있지 않습니다. 예를 들어, DOM 파서는 메모리에 DOM 트리를 작성하고 문서의 모든 부분에 반복적으로 액세스하고 DOM 트리를 수정할 수 있기 때문에 기능이 풍부하지만 문서가 크면 공간이 비효율적입니다 , 작업 방법을 배우는 데 약간의 시간이 걸립니다. 그러나 SAX 구문 분석기는 입력 문서가 큰 경우 (내부 구조를 작성하지 않기 때문에) 훨씬 공간 효율적입니다. 또한 API가 실제로 단순하기 때문에 DOM 파서보다 더 빠르게 실행하고 배우기 쉽습니다. 그러나 기능적인 관점에서 더 적은 기능을 제공하므로 사용자 자신의 데이터 구조 작성과 같이 사용자가 더 많은 정보를 처리해야합니다. 그런데 좋은 파서는 무엇입니까? 대답은 실제로 응용 프로그램의 특성에 달려 있다고 생각합니다.
DOM 파서를 사용하는 것보다 SAX 파서를 사용하는 것이 유리한 실제 응용 프로그램은 무엇입니까? DOM 파서와 SAX 파서의 일반적인 응용 프로그램은 무엇입니까?
다음과 같은 경우 SAX 파서를 사용하는 것이 DOM 파서를 사용하는 것보다 유리합니다.
- 입력 문서가 사용 가능한 메모리에 비해 너무 큽니다 (실제로 SAX가 유일한 선택입니다)
- 작은 연속 입력으로 문서를 처리 할 수 있습니다. 유용한 작업을 수행하기 전에 전체 문서가 필요하지 않습니다
- 파서를 사용하여 관심 정보를 추출하고 모든 계산은 사용자가 만든 데이터 구조를 완전히 기반으로합니다. 실제로 대부분의 응용 프로그램에서 우리는 일반적으로 DOM 트리만큼 복잡하지 않은 자체 데이터 구조를 만듭니다. 이런 의미에서 DOM 파서를 사용할 가능성은 SAX 파서를 사용하는 것보다 적습니다.
다음과 같은 경우 SAX 파서를 사용하는 것보다 DOM 파서를 사용하는 것이 유리합니다.
- 응용 프로그램은 문서의 여러 부분에 동시에 액세스해야합니다.
- 응용 프로그램은 아마도 문서 자체만큼이나 복잡한 내부 데이터 구조를 사용할 수 있습니다.
- 응용 프로그램은 문서를 반복해서 수정해야합니다.
- 애플리케이션은 많은 메소드 호출을 통해 문서를 상당한 시간 동안 저장해야합니다.
예 (DOM 파서 또는 SAX 파서를 사용 하시겠습니까?) :
강사가 학생의 모든 개인 정보와 수업 시간에 학생의 점수를 포함하는 XML 문서를 가지고 있다고 가정하고 이제는 응용 프로그램을 사용하여 학생들에게 최종 성적을 부여하고 있습니다. 그가 만들고자하는 것은 SSN과 성적 목록입니다. 또한 우리는 그의 응용 프로그램에서 강사가 학생 개인 정보와 포인트를 저장하기 위해 배열과 같은 데이터 구조를 사용하지 않는다고 가정합니다. 강사가 학급 평균 이상을 얻은 사람들에게 A를주고 다른 사람들에게 B를 주기로 결정한 경우, 그의 응용 프로그램에서 DOM 파서를 사용하는 것이 좋습니다. 그 이유는 전체 문서가 처리되기 전에 수업 평균이 얼마인지 알 수 없기 때문입니다. 그가 자신의 응용 프로그램에서해야 할 일은 먼저 모든 학생들의 점수를 매기고 평균을 계산 한 다음 문서를 다시 살펴보고 자신이 얻은 점수를 학급 평균과 비교하여 각 학생에게 최종 성적을 할당합니다. 그러나 강사가 90 점 이상을받은 학생에게 A가 할당되고 다른 학생에게 B가 할당되는 채점 정책을 채택하는 경우 SAX 파서를 사용하는 것이 좋습니다. 그 이유는 각 학생에게 최종 성적을 부여하기 위해 전체 문서가 처리 될 때까지 기다릴 필요가 없기 때문입니다. SAX 파서가이 학생의 성적을 읽으면 즉시 학생에게 성적을 할당 할 수 있습니다. 위의 분석에서 우리는 강사가 자신의 데이터 구조를 만들지 않았다고 가정했습니다. SSN을 저장하는 문자열 배열과 포인트를 저장하는 정수 배열과 같은 자체 데이터 구조를 만드는 경우 어떻게됩니까? 이 경우 SAX가 메모리와 시간을 절약하면서도 작업을 완료하기 전에 SAX가 더 나은 선택이라고 생각합니다. 이 예제에서 한 가지 더 고려해야 할 사항이 있습니다. 강사가 원하는 것은 목록을 인쇄하는 것이 아니라 업데이트 된 각 학생의 성적과 함께 원본 문서를 다시 저장하는 것입니까? 이 경우, 어떤 등급 정책을 채택하든 DOM 파서는 더 나은 선택이되어야합니다. 그는 자신의 데이터 구조를 만들 필요가 없습니다. 그가해야 할 일은 먼저 DOM 트리를 수정하고 (즉, 'grade'노드로 값을 설정 한 후) 수정 된 전체 트리를 저장하는 것입니다. 만약 그가 DOM 파서 대신 SAX 파서를 사용하기로 선택한다면,이 경우 그는 작업을 수행하기 전에 DOM 트리와 거의 같은 데이터 구조를 만들어야합니다. 아직 작업을 완료하십시오. 이 예제에서 한 가지 더 고려해야 할 사항이 있습니다. 강사가 원하는 것은 목록을 인쇄하는 것이 아니라 업데이트 된 각 학생의 성적과 함께 원본 문서를 다시 저장하는 것입니까? 이 경우, 어떤 등급 정책을 채택하든 DOM 파서는 더 나은 선택이되어야합니다. 그는 자신의 데이터 구조를 만들 필요가 없습니다. 그가해야 할 일은 먼저 DOM 트리를 수정하고 (즉, 'grade'노드로 값을 설정 한 후) 수정 된 전체 트리를 저장하는 것입니다. 만약 그가 DOM 파서 대신 SAX 파서를 사용하기로 선택한다면,이 경우 그는 작업을 수행하기 전에 DOM 트리와 거의 같은 데이터 구조를 만들어야합니다. 아직 작업을 완료하십시오. 이 예제에서 한 가지 더 고려해야 할 사항이 있습니다. 강사가 원하는 것은 목록을 인쇄하는 것이 아니라 업데이트 된 각 학생의 성적과 함께 원본 문서를 다시 저장하는 것입니까? 이 경우, 어떤 등급 정책을 채택하든 DOM 파서는 더 나은 선택이되어야합니다. 그는 자신의 데이터 구조를 만들 필요가 없습니다. 그가해야 할 일은 먼저 DOM 트리를 수정하고 (즉, 'grade'노드로 값을 설정 한 후) 수정 된 전체 트리를 저장하는 것입니다. 만약 그가 DOM 파서 대신 SAX 파서를 사용하기로 선택한다면,이 경우 그는 작업을 수행하기 전에 DOM 트리와 거의 같은 데이터 구조를 만들어야합니다. 하지만 각 학생의 성적이 업데이트 된 원본 문서를 다시 저장하려면? 이 경우, 어떤 등급 정책을 채택하든 DOM 파서는 더 나은 선택이되어야합니다. 그는 자신의 데이터 구조를 만들 필요가 없습니다. 그가해야 할 일은 먼저 DOM 트리를 수정하고 (즉, 'grade'노드로 값을 설정 한 후) 수정 된 전체 트리를 저장하는 것입니다. 만약 그가 DOM 파서 대신 SAX 파서를 사용하기로 선택한다면,이 경우 그는 작업을 수행하기 전에 DOM 트리와 거의 같은 데이터 구조를 만들어야합니다. 하지만 각 학생의 성적이 업데이트 된 원본 문서를 다시 저장하려면? 이 경우, 어떤 등급 정책을 채택하든 DOM 파서는 더 나은 선택이되어야합니다. 그는 자신의 데이터 구조를 만들 필요가 없습니다. 그가해야 할 일은 먼저 DOM 트리를 수정하고 (즉, 'grade'노드로 값을 설정 한 후) 수정 된 전체 트리를 저장하는 것입니다. 만약 그가 DOM 파서 대신 SAX 파서를 사용하기로 선택한다면,이 경우 그는 작업을 수행하기 전에 DOM 트리와 거의 같은 데이터 구조를 만들어야합니다. 노드)를 수정 한 다음 수정 된 전체 트리를 저장하십시오. 만약 그가 DOM 파서 대신 SAX 파서를 사용하기로 선택한다면,이 경우 그는 작업을 수행하기 전에 DOM 트리와 거의 같은 데이터 구조를 만들어야합니다. 노드)를 수정 한 다음 수정 된 전체 트리를 저장하십시오. 만약 그가 DOM 파서 대신 SAX 파서를 사용하기로 선택한다면,이 경우 그는 작업을 수행하기 전에 DOM 트리와 거의 같은 데이터 구조를 만들어야합니다.
예
문제점 설명 : 주어진 XML 문서의 요소 인 원에 대한 모든 정보를 추출하는 Java 프로그램을 작성하십시오. 각 원 요소에는 세 가지 하위 요소 (예 : x, y 및 반지름)와 색상 속성이 있다고 가정합니다. 샘플 문서는 다음과 같습니다.
<?xml version="1.0"?>
<!DOCTYPE shapes [
<!ELEMENT shapes (circle)*>
<!ELEMENT circle (x,y,radius)>
<!ELEMENT x (#PCDATA)>
<!ELEMENT y (#PCDATA)>
<!ELEMENT radius (#PCDATA)>
<!ATTLIST circle color CDATA #IMPLIED>
]>
<shapes>
<circle color="BLUE">
<x>20</x>
<y>20</y>
<radius>20</radius>
</circle>
<circle color="RED" >
<x>40</x>
<y>40</y>
<radius>20</radius>
</circle>
</shapes>
DOMparser를 사용한 프로그램
import java.io.*;
import org.w3c.dom.*;
import org.apache.xerces.parsers.DOMParser;
public class shapes_DOM {
static int numberOfCircles = 0; // total number of circles seen
static int x[] = new int[1000]; // X-coordinates of the centers
static int y[] = new int[1000]; // Y-coordinates of the centers
static int r[] = new int[1000]; // radius of the circle
static String color[] = new String[1000]; // colors of the circles
public static void main(String[] args) {
try{
// create a DOMParser
DOMParser parser=new DOMParser();
parser.parse(args[0]);
// get the DOM Document object
Document doc=parser.getDocument();
// get all the circle nodes
NodeList nodelist = doc.getElementsByTagName("circle");
numberOfCircles = nodelist.getLength();
// retrieve all info about the circles
for(int i=0; i<nodelist.getLength(); i++) {
// get one circle node
Node node = nodelist.item(i);
// get the color attribute
NamedNodeMap attrs = node.getAttributes();
if(attrs.getLength() > 0)
color[i]=(String)attrs.getNamedItem("color").getNodeValue();
// get the child nodes of a circle node
NodeList childnodelist = node.getChildNodes();
// get the x and y value
for(int j=0; j<childnodelist.getLength(); j++) {
Node childnode = childnodelist.item(j);
Node textnode = childnode.getFirstChild();//the only text node
String childnodename=childnode.getNodeName();
if(childnodename.equals("x"))
x[i]= Integer.parseInt(textnode.getNodeValue().trim());
else if(childnodename.equals("y"))
y[i]= Integer.parseInt(textnode.getNodeValue().trim());
else if(childnodename.equals("radius"))
r[i]= Integer.parseInt(textnode.getNodeValue().trim());
}
}
// print the result
System.out.println("circles="+numberOfCircles);
for(int i=0;i<numberOfCircles;i++) {
String line="";
line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
System.out.println(line);
}
} catch (Exception e) {e.printStackTrace(System.err);}
}
}
SAXparser를 이용한 프로그램
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class shapes_SAX extends DefaultHandler {
static int numberOfCircles = 0; // total number of circles seen
static int x[] = new int[1000]; // X-coordinates of the centers
static int y[] = new int[1000]; // Y-coordinates of the centers
static int r[] = new int[1000]; // radius of the circle
static String color[] = new String[1000]; // colors of the circles
static int flagX=0; //to remember what element has occurred
static int flagY=0; //to remember what element has occurred
static int flagR=0; //to remember what element has occurred
// main method
public static void main(String[] args) {
try{
shapes_SAX SAXHandler = new shapes_SAX (); // an instance of this class
SAXParser parser=new SAXParser(); // create a SAXParser object
parser.setContentHandler(SAXHandler); // register with the ContentHandler
parser.parse(args[0]);
} catch (Exception e) {e.printStackTrace(System.err);} // catch exeptions
}
// override the startElement() method
public void startElement(String uri, String localName,
String rawName, Attributes attributes) {
if(rawName.equals("circle")) // if a circle element is seen
color[numberOfCircles]=attributes.getValue("color"); // get the color attribute
else if(rawName.equals("x")) // if a x element is seen set the flag as 1
flagX=1;
else if(rawName.equals("y")) // if a y element is seen set the flag as 2
flagY=1;
else if(rawName.equals("radius")) // if a radius element is seen set the flag as 3
flagR=1;
}
// override the endElement() method
public void endElement(String uri, String localName, String rawName) {
// in this example we do not need to do anything else here
if(rawName.equals("circle")) // if a circle element is ended
numberOfCircles += 1; // increment the counter
}
// override the characters() method
public void characters(char characters[], int start, int length) {
String characterData =
(new String(characters,start,length)).trim(); // get the text
if(flagX==1) { // indicate this text is for <x> element
x[numberOfCircles] = Integer.parseInt(characterData);
flagX=0;
}
else if(flagY==1) { // indicate this text is for <y> element
y[numberOfCircles] = Integer.parseInt(characterData);
flagY=0;
}
else if(flagR==1) { // indicate this text is for <radius> element
r[numberOfCircles] = Integer.parseInt(characterData);
flagR=0;
}
}
// override the endDocument() method
public void endDocument() {
// when the end of document is seen, just print the circle info
System.out.println("circles="+numberOfCircles);
for(int i=0;i<numberOfCircles;i++) {
String line="";
line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
System.out.println(line);
}
}
}