<?php
	/*
		Author: 	Sean Nicholls
		
		Website: 	http://www.seannicholls.com/
		
		Contact: 	http://www.seannicholls.com/contact 
				info [at] seannicholls [dot] com  (that anti-spam trick wont work forever!)
				
		Date: 	18 January 2007 to 29 January 2007
		
		Version:	0.1a	has not been tested thoroughly. only sparsely.
				please help me by testing this script and reporting
				your results to me.
		
		Copyright:	Creative Commons Attribute/ShareAlike 2.5 (free stuff is good!)
				http://creativecommons.org/licenses/by-sa/2.5/
		
		Legal:	Provided AS-IS with no warranty or guarantee whatsoever.
				Freedom is only as good as your wallet.
				
		Comments:	this source is in-production. I would strongly advise against using it
				in its current state as it has not yet been fully tested. If you wish to
				test it and provide feedback, I would greatly apreciate the help.
		
		Notes:	n/a
	*/
	
	class xmlDocument
	{
		// data
		public $xml = array();
		public $attributes = array();
		
		// constructor
		function xmlDocument( $ver='1.0', $enc=null , $nspace=null )
		{
			if( is_array($ver) && count($ver) > 0 )
			{
				$this->attributes = $ver;
			}
			else
			{
				if( is_string($ver) && strlen($ver) > 0 )
					$this->attributes[0] = new xmlAttribute( 'version' , $ver );
					
				if( is_string($enc) && strlen($enc) > 0 )
					$this->attributes[1] = new xmlAttribute( 'encoding' , $enc );
					
				if( is_string($nspace) && strlen($nspace) > 0 )
					$this->attributes[2] = new xmlAttribute( 'namespace' , $nspace );
			}
		}
		
		// methods
		function addElement( $elm=null, $val=null, $att=null, $cdata=false )
		{
			array_push( $this->xml , new xmlElement( $elm, $val, $att, $cdata ) );
		}
		
		// properties
		function toString()
		{
			$out = '<?xml';
			
			if( count($this->attributes) > 0 )
			{
				for( $i=0; $i<count($this->attributes); $i++ )
					$out .= ' ' . $this->attributes[$i]->toString();
			}
				
			$out .= ' ?>';
			
			
			for( $i=0; $i<count($this->xml); $i++ )
				if( $this->xml[0] instanceof xmlElement )
					$out .= $this->xml[$i]->toString();
				
			return $out;
		}
		function toBrowser()
		{
			header('Content-type: text/xml');
			
			$out = $this->toString();
			
			if( strtolower($this->attributes[1]->xml['xmlAttributeValue']) == 'utf-8' )
				utf8_encode($out);
			
			die($out);
		}
		function toArray()
		{
			return $this->xml;
		}
	
	}
	
	class xmlElement
	{
		// data
		public $xml;
		
		// constructor
		function xmlElement( $elm=null, $val=null, $att=null, $cdata=false )
		{
			if( $elm != null && is_string($elm) )
				$this->xml['xmlElementName'] = $elm;
				
			if( $val != null && (is_string($val) || $val instanceof xmlElement || is_array($val)) )
				$this->xml['xmlElementValue'] = $val;
				
			if( $att != null && (is_array($att) || $att instanceof xmlAttribute) )
			{
				$this->xml['xmlElementAttributes'] = $att;
			}
			
			if( is_bool($cdata) )
				$this->xml['xmlElementCData'] = $cdata;
		}
				
		// methods
		function addElement( $elm=null, $val=null, $att=null, $cdata=false )	// using this on an element with string data will erase that data. use carefully.
		{
			if( !is_array($this->xml['xmlElementValue']) )
				$this->xml['xmlElementValue'] = array(); 
			
			if( !($elm instanceof xmlElement) )
				$elm = new xmlElement( $elm, $val, $att, $cdata );
				
			array_push( $this->xml['xmlElementValue'] , $elm );
		}
		
		// properties
		function toString()
		{
			$out = '<' . $this->xml['xmlElementName'];
			
			if( $this->xml['xmlElementAttributes'] != null )
			{
				if( is_array($this->xml['xmlElementAttributes']) )
				{
					for( $i=0; $i < count($this->xml['xmlElementAttributes']); $i++ )
						$out .= ' ' . $this->xml['xmlElementAttributes'][$i]->toString();	
				}
				else
				{
					$out .= ' ' . $this->xml['xmlElementAttributes']->toString();
				}
			}
			
			if( $this->xml['xmlElementValue'] instanceof xmlElement )
			{
				return $out .= '>' . $this->xml['xmlElementValue']->toString() . '</' . $this->xml['xmlElementName'] . '>';
			}
			else if( is_array($this->xml['xmlElementValue']) )
			{
				$out .= '>';
				
				for( $i=0; $i<count($this->xml['xmlElementValue']); $i++ )
					$out .= $this->xml['xmlElementValue'][$i]->toString();
				
				return $out .= '</' . $this->xml['xmlElementName'] . '>';
			}
			else
			{
				if( strlen($this->xml['xmlElementValue']) <= 0 )
				{
					return( $out .= ' />' );
				}
				else if( $this->xml['xmlElementCData'] )	
				{
					return( $out .= '><![CDATA[' . $this->xml['xmlElementValue'] . ']]></' . $this->xml['xmlElementName'] . '>' );
				}
				else
				{
					return( $out .= '>' . $this->xml['xmlElementValue'] . '</' . $this->xml['xmlElementName'] . '>' );
				}
			}
		}
		function toArray()
		{
			return $this->xml;
		}
	}
	
	class xmlAttribute
	{
		// data
		public $xml;
	
		// constructor
		function xmlAttribute( $name=null , $val=null )
		{		
			if( $name != null && $val != null )
			{
				$xml = array();
		
				if( is_string($name) && strlen($name) > 0 )
					$this->xml['xmlAttributeName'] = $name;
					
				if( is_string($val) && strlen($val) > 0 )
					$this->xml['xmlAttributeValue'] = $val;
			}
			else
			{
				// incorreclty formatted instantiation
			}
		}

		// properties
		function toString()
		{
			return $this->xml['xmlAttributeName'] . '="' . $this->xml['xmlAttributeValue'] . '"';
		}
		function toArray()
		{
			return $this->xml;
		}
	}

?>
