IT_Programming/XML

[PHP] XML 문서파싱 - SAX 방식 , DOM 방식

JJun ™ 2007. 9. 30. 13:05

XML 문서파싱은 PHP에서 제공하는 파서로 한다.

SAX(Simple API for XML) 파서, DOM(Document Object Model) 방식 파서 2가지가 있다.

 

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

 

SAX 방식

 

: 엘리먼트, 처리지시문, 선언문 등 XML문서 구성요소를 읽어들일때마다 이벤트를 발생시켜서

  처리, 빠르나 한번 처리한 데이터를 다시 이용할 수 없는 단점. 용량이 큰 문서나 많은 문서를

  처리할 때 적절

 

- SAX 파서의 경우 Start Tag, End Tag를 만나면 이벤트를 발생시킴.

   xml_set_element_handler()함수 이용 처리...

 

cf. DOM 방식 : 전체문서를 메모리에 저장하고 처리하는 방식으로 상대적으로 느림

 

 

SAX 파싱을 위한 함수

 

1. xml_parser_create : 파서 생성

2. xml_parser_free : 생성된 파서 해제

3. xml_parse(resource parser, string data [,bool is_final]) : xml 문서를 파싱한다.

- 파싱할 때 문자열에 저장해 한꺼번에 하는 방법과 fopen(), fget() 함수를 사용하여 여러조각으로 나누어 파싱하는 방법이 있는데 후자때문에 'is_final' 값을 이용하여 문서의 마지막 데이터인지 확인필요

 

[한꺼번에 파싱]

if(!@xml_parse($xml_parser,$document_xml,TRUE))
 {
 die ("error acurred during parsing");
 }

 

[나누어서 파싱]

$fp = @fopen("book.xml","r") or die("failed to get file");

while(!feof($fp))
{
 $data = fgets($fp);
 if(!xml_parse($xml_parser,$data,feof($fp)))
 {
  die ("error accurred during parsing");
 }
}

 

4. xml_get_current_line_number (resource parser) : 현재파싱하고 있는 문서 줄번호 반환

5. xml_get_current_column_number (resource parser) : 현재파싱하고 있는 열번호 반환

6. xml_get_error_code (resource parser) : 에러코드를 반환

7. xml_error_string(int error code) : 에러메시지 반환

 

[샘플] 위 4개를 이용하면 XML문서자체의 구조에러를 찾아내는 데 좋을 것 같다.

 

$fp = @fopen("abnormal_book.xml","r") or die("failed to get file");

while(!feof($fp))
{
 $data = fgets($fp);
 if(!xml_parse($xml_parser,$data,feof($fp)))
 {
  die ("error accurred during parsing."."
\n"." error : ".xml_get_current_line_number($xml_parser)."line".xml_get_current_column_number($xml_parser)."column
\n"."error Message : ".xml_error_string(xml_get_error_code($xml_parser)));
 }
}

 

8. xml_set_element_handler($xml_parser,"startElement","endElement") : 앨리먼트 핸들러  정의

- 시작태그 핸들러의 속성값들은 Array 형태로 인자값을 넘겨준다.따라서 startElement 함수는 Array 값을 처리하는 형태로 로직구성됨.

 

[샘플]

function startElement($parser,$name,$attr)
{
 $output="";
 $output.="<".$name;
 if(is_array($attr)&&sizeof($attr)>0)
 {
  while(list($attr_name,$attr_value)=each($attr))
  {
   $output.="".$attr_name."=\"".$attr_value."\"";
  }
 }

 $output.=">";
 echo $output;
}

 

9. xml_parse_set_option(resource parser, int option, mixed value) : 파싱 옵션지정

1) XML_OPTION_CASE_FOLDING : TRUE 또는 FALSE

2) XML_OPTION_TARGET_ENCODING : "ISO-8859-1","UTF-8","US_ASCII"

3) XML_OPTION_SKIP_WHITE : TRUE 또는 FALSE

 

[샘플]

xml_set_element_handler($xml_parser,"startElement","endElement"); // event handler 정의
xml_set_character_data_handler($xml_parser,"characterData");
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,FALSE);

 

10. xml_parser_get_option(resource parser, int option) : 설정된 옵션값 반환

 

11. xml_set_character_data_handler(resource parser,callback handler) : 캐릭터 데이터 만났을 때 호출되는 이벤트 핸들러 정의

- 공백, 개행도 문자로 보기 때문에 예상과 다른 횟수만큼 characterData() 함수가 호출됨. 이를 보정할 수 있음

-

 

[샘플]

xml_set_character_data_handler($xml_parser,"characterData");

function characterData($parser,$cdata)
{
 echo "<b>".iconv("UTF-8","EUC-KR",$cdata)."</b>";
}

 

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

 

DOM (Document Object Model) 방식

 

W3C가 국제표준으로 제안한 XML 프로그래밍 인터페이스

XML문서를 구성하는 각각의 구성요소를 객체모델링화함으로써 객체가 가진 '속성'과 '메소드'를 통해 문서의 구조와 데이터를 다룰 수 있도록 정의한 표준화된 프로그래밍 인터페이스

 

그러나, 실제 문서를 처리하는 클래스는 C#, 자바, PHP같은 프로그래밍언어에서 지원하며, DOM API는 표준규약만을 제공한다. 따라서 프로그래밍 언어나 운영체제에 중립적이고 독립적임.

 

DOM 파서는 XML 문서를 해석하여 DOMTree형태로 메모리에 올린다.

이 DOMTree 에 PHP로 작성한 응용프로그램은 DOM API를 통해 접근, 제어,처리한다.

PHP에서 제공하는 DOM API는 모드 클래스형태로 지원되고 있으며, 따라서 객체지향프로그래밍에 대한 기초가 있어야 이해가능하다.

XML 문서가 메모리에 올라온 형태인 DOM Tree 에 접근하기 위해 사용해야 하는

DOM API 중 가장 기본적이고 많이 쓰이는 것이 DOMDocument 클래스이다.

DOMDocument 클래스는 XML이나 HTML 문서를 모델링한 클래스이다. 이를 이용하여

새로운 문서를 생성하거나 이미 존재하는 문서구조에 새로운 노드를 추가할 수도 있다.

 

DOMDocument 클래스의 속성은 읽을수만 있는지.. API를 통해 속성을 변화시킬 수 있는지

여부에 따라서 ReadOnly와 Read&Write 타입의 속성을 가질 수 있다.

 

 

 

1. DOMDocument 클래스의 속성

 

[readonly DOMElement documentElement]

 

루트앨리먼트 노드, 즉 문서의 최상위 앨리먼트를 가리키는 속성

 

$book = new DOMDocument();

$book->loadXML("Requirement Analysis");

 

echo get_class($book->documentElement).",node name :".$book->documentElement->nodeName;

?>

 

XML 문서를 생성시키고 루트앨리먼트의 이름과 노드이름을 출력하는 예제

 

[readonly DOMDocumentType doctype]

 

[version]

[encoding]

[preserveWhiteSpace] 앨리먼트 사이에 공백문자 처리여부 속성, 기본값 True, 공백을 가지고

                                 파싱한다.

[documentRUI] XML 문서의 저장경로

[formatOutput] 보여지는 데로 XML 문서 출력하는 여부, 기본값 False

 

 

2. DOMDocument 클래스의 메소드

 

loadXML()  - XML 문서를 불러온다.

saveXML() - 메모리에 올라가 있는 DOM Tree 를 XML문서로 변환한다.

load() - 파일로 부터 XML 문서를 불러온다.

save() - DOM Tree를 파일로 저장한다.

validate() - DTD를 기준으로 XML 문서의 유효성을 검증한다.

schemaValidate() - XML 스키마를 기준으로 XML 문서의 유효성을 검증한다.

schemaValidateSource() - XML 스키마를 기준으로 XML 문서의 유효성을 검증한다.

createElement() - 새로운 앨리먼트 노드 생성

createTextNode() - 새로운 텍스트 노드 생성

createAttribute() - 새로운 속성 노드 생성

createElementNS() - 네임스페이스 영역을 갖는 앨리먼트 노드 생성

createAttibuteNS() - 네임스페이스 영역을 갖는 속성 노드 생성

createComment() - 새로운 주석노드 생성

createCDATASection() - 새로운 CDATA 섹션 노드를 생성한다.

getElementsByTagName() - 지정한 태그명을 갖는 앨리먼트의 노드 리스트 출력

getElementsByTagNameNS() - 특정한 네임스페이스 영역에서 지정한 태그명을 갖는 앨리먼트의

                                              노드리스트를 반환한다.

importNode - XML 문서에 붙일 특정노드를 가져온다.

 

 

 

 

DOM API로  새로운 XML 문서 작성하기

  

// DOM 객체 및 루트앨리먼트 생성

 

$doc = new DOMDocument();

$doc->loadXML("");

 

// 앨리먼트 생성. 생성 후 추가해야 함

$bookNode = $doc->createElement("book"); // 노드 생성

$doc->documentElement->appendChild($bookNode); // 노드 추가

 

// 새로생성된 book노드에 isbn 속성 생성 및 추가

$isbnNode = $doc->createAttibute("isbn");

$isbnNode->value="19999999";

$bookNode->setAttributeNode($isbnNode);

 

// subject , authors 앨리먼트 생성

$subjectNode = $doc->createElement("subject","Test Book");

$authorsNode=$doc->createElement("authors");

 

// author 앨리먼트 생성, 자식 노드 추가

$authorsNode->appendChild(new DOMElement("author","Craig Walls"));

$authorsNode->appendChild(new DOMElement("author","Norman Richards"));