<?php
function random_code($type="D", $code_num=32){
$letter = NULL;
if($type == "A" or $type == "D") $letter = "azertyuiopqsdfghjklmwxcvbn";
if($type == "B" or $type == "D") $letter .= "AZERTYUIOPQSDFGHJKLMWXCVBN";
if($type == "C" or $type == "D") $letter .= "0123456789";
$max = strlen($letter)-1;
$code = null;
for($i=0; $i < $code_num; $i++) $code .= $letter{mt_rand(0, $max)};
return $code;
}
/*URL 검사기
*/
function is_url($url){
if(preg_match("[^http://|^https://|^ftp://]", $url)){
$info = parse_url($url);
$info['type'] = "internet";
return $info;
}
elseif(preg_match("[/|\\\\|\.+([A-Za-z])]", $url)){
$info = pathinfo($url);
$info['type'] = "localhost";
return $info;
}
else return FALSE;
//if(preg_match($pattern, $url)) return TRUE;
//else return FALSE;
}
class domXml{
/*
* domXML 클래스 아주 중요한 클래스들이다.
* 사용법:
* 1번 방법
* $this->{'data'} = "<data><title></title></data>";
* 위에 처럼하면 data로 호출시 위에 데이터가 들은 DOM객체를 반환한다.
*
* 2번 방법
* $this->{'http://babo.net/나XML.xml'};
* 위에 처럼하면 http://babo.net/wow.xml로 호출시 해당 xml의 데이터가 들은 DOM객체를 반환
* 3번방법
* $this->{'wow2.xml'} = "<data><title></title></data>";
* XML 확장자를 가진 이름이면 주소가 없으면 해당 자료를을 넣은 데이터의 DOM을 반환한다.
* !!주의 할것은 이미 파일이 있으면 에러가 걸리니 주의 해라.
*
* !!!!이미 있는 파일 변조하고 다시 저장시.
* $this->{'나XML.xml'} = $this->{'나XML.xml'}->firstChild->ownerDocument;
*
* 이렇게 다시 Document를 넣으면 종료 될때 자동 저장된다.
* 주의:: 같은 DOM객체여야 한다. 서로 틀린 DOM 경우 전혀 안된다. 프로토콜로 시작하는 이름은 에러가 걸리니 주의 해라.
*
* 이하 메소드 설명 귀찮아서 안함.
*/
private $version, $encoding;
private $stand_by_save = array();
private Static $xml_key = array(), $node = array();
private $nowDom;
private Static $classDomXml = false;
public Static function classLoad($version="1.0", $encoding="utf-8", $load = true){
if(!domXml::$classDomXml and $load) return domXml::$classDomXml = new domXml($version, $encoding);
else return domXml::$classDomXml;
}
function __construct($version, $encoding){
$this->version = $version;
$this->encoding = $encoding;
}
/********************
1번 일반키
2번 로컬 파일
3번 원격지 파일
********************/
final private function info_check($key){
$info = is_url($key);
switch($info['type']){
case "internet":
return $info;
break;
case "localhost":
$info['file_exists'] = file_exists($key);
return $info;
break;
default:
$info['type'] = "key";
return $info;
break;
}
}
final private function is_info($key){
if(isset($xml_key[$key])) return $xml_key[$key];
else return self::$xml_key[$key] = $this->info_check($key);
}
//호출시
//키가 존재하면 반환하고 아니면 로드을 호출한다.
final public function &__get($key){
switch(isset(self::$node[$key])){
case(TRUE):
return self::$node[$key];
break;
case(FALSE):
if($dom = $this->load($key)) self::$node[$key] = $dom;
return $dom;
break;
}
}
//입력시
//키가 존재 안 하면 미리 세팅한다고 판단 세이브 평션을 호출한다.
//키가 존재 하면 저장한다고 판단 세이브를 한다.랜덤 코드를 비교해서 같으면 저장 아니면 거부 한다.
final public function __set($key, $var){
switch(isset(self::$node[$key])){
case(FALSE):
$node = $this->save($key, $var);
if($node) {
self::$node[$key] = $node;
}
break;
case(TRUE):
$info = $this->info_check($key);
if(($info['type'] == "localhost" and $info['file_exists'])and $this->check_code(self::$node[$key]) == $this->check_code($var)){
$this->stand_by_save($key);
self::$node[$key] = $var;
}
break;
}
}
final private function check_code($node){
return $node->documentElement->ownerDocument->check_code;
}
final private function load($var){
$info = $this->is_info($var);
$dom = new \DOMDocument($this->version, $this->encoding);
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
//그냥 일반키면 거부값 보내기
if($info['type'] == "key"){
unset($dom);
return false;
}
//로컬 파일이면 이때 파일이 있으면 로드하고 없으면 일반키 처럼 처리.
elseif($info['type'] == "localhost"){
if($info['file_exists']) $dom->load($var);
else return false;
}
//리모트호스트면 세이브가 불가능함.
elseif($info['type'] == "internet") $dom->load($var);
$dom->check_code = random_code("C", 10);
return $dom;
}
final private function save($key, $var){
$info = $this->is_info($key);
//그냥 일반키면 넘어간다.
//로컬 파일이면 이때 파일이 있으면 에러를 보낸다.
if($info['type'] == "localhost"){
if($info['file_exists']) return false;
else $this->stand_by_save($key);
}
//원격지면면 에러를 보낸다,
elseif($info['type'] == "internet") return false;
$dom = new DOMDocument($this->version, $this->encoding);
$dom->preserveWhiteSpace = false;
$dom->loadxml("<?xml version=\"".$this->version."\" encoding=\"".$this->encoding."\" ?>".$var);
$dom->check_code = random_code("C", 10);
$dom->formatOutput = TRUE;
return $dom;
}
//작업을 완료되면 자동으로 세이브함
final function __destruct(){
foreach($this->stand_by_save as $key => $var) $this->completion($key);
}
//클래스 소멸시 자동으로 저장할 목록 저장.
final private function stand_by_save($key){
$this->stand_by_save[$key]=$key;
}
//저장하기.
/*절대 경로를 넣은 이유가 클래스가 unset없이
소멸자를 호출시 이상한 곳에 파일을 만들기에 넣는다.*/
final public function completion($key){
self::$node[$key]->save($key);
}
}
?>
제가 쓰고 있는 XML로드 클래스 입니다.
위에 주석문에도 있지만 소스가 보기에는 난잡해서 여기다 다시 적어 드려요.
그리고 아직 몇가지 문제점이 보이는데 제가 쓰는대 아무 문제가 없는 관계로;;
차후에 필요하면 고쳐서 다시 올릴게요.
(참고로 소스가 난잡하게 보인것은 tab을 써서 그래요.)
$test = new xmlDom();
첫번째 방법으로 일반키 적용으로
$test->{'data'} ="<data></data>";
이렇게 하면 $test->{'data'}에 <data></data>적용된 DOMDocument가
들어가게 됩니다. 부를떄는 $test->{'data'} 이렇게 부르면 됩니다.
해당 자료가 없으면 FALSE 값을 내놓습니다.
원격지 파일 부르기.
두번째는 $test->{'http://aa.kr/s.xml'}로 부르면 역시나 DOMDocument이 들어가게 됩니다.
아 여기서 $dom = $test->{'http://aa.kr/s.xml'} 이런분들이 간혹 존재 할걸로 예상 되는데 이러면 절대 안됩니다.
$test->{'http://aa.kr/s.xml'};
$dom = $test->{'http://aa.kr/s.xml'};
이렇게 하셔야 합니다. 한번 로드 된것은 Static에 저장 되기에 여러번 로드해도 문제 없답니다.
로컬 파일 부르기.
로컬 파일은 역시나 $test->{'/home/www/s.xml'} 이렇게 하시면 됩니다.
로컬파일은 세이브가 지원 되는데. 여기서 문제가 있습니다.
로드만 하면 문제가 없습니다. 세이브 쓴다면 하면 꼭 절대 경로로 파일을 불러주세요.
안 그러면 세이브 할때 데이터가 아파치 경로에다 만들어 버립니다.
왜 그런지는 나도 모릅니다.
세이브 방법은
$this->{'/home/www/s.xml'} = $this->{'/home/www/s.xml'}->firstChild->ownerDocument;
이렇게 하시면 됩니다.
이후 절대 적인 관심이나 오타 그리고 지적좀 알려주세요.