Location: PHPKode > projects > Attachment_doc > attachment_doc/includes/openoffice2html.php
<?php
/*****************************************************************************************
*															Clase OpenOffice2html
*
* 	Author: 		Luis Miguel Cabezas Granado
* 	Nick:				Hazard_Cool, MagoLope
*		Licencia:		GPL
* 	Language:		Spanish
*
*  	This program is free software; you can redistribute it and/or modify
*  	it under the terms of the GNU General Public License as published by
*  	the Free Software Foundation; either version 2 of the License, or
*  	(at your option) any later version.
*
*  	This program is distributed in the hope that it will be useful,
*  	but WITHOUT ANY WARRANTY; without even the implied warranty of
*  	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  	GNU Library General Public License for more details.
*
*  	You should have received a copy of the GNU General Public License
*  	along with this program; if not, write to the Free Software
*  	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*		TODO:
*		predefined styles, list, number list, better images proccess, error control, all
*
******************************************************************************************/

class OpenOffice2html
	{

//Variable que muestra la versión de la clase

	var $version = "OpenOffice2html-0.1.1 Alfa by Hazard_Cool, MagoLope";
	var $columnas = 1;
	var $puntero_pila = 1;

//Constructor. Se encarga de descomprimir un fichero de OpenOffice (.sxw)
//en el directorio tmp/ y después parsea el archivo content.xml que es el
//que contiene la mayoría de los datos del documento.

	function OpenOffice2html($fichero, $dirname_sxw, $prefixname_sxw)   
		{

//Imprime en pantalla la versión de la clase y algunos datos del programador
		
		$this->version();
		
//Asocia al la variable de la clase fichero_sxw el fichero pasado al objeto, descomprime mediante el
//método descomprimir_sxw y se crea un parse de XML para leer el archivo content.xml

		$this->desdirname=$dirname_sxw;
		$this->desprefixname=$prefixname_sxw;
		$this->fichero_sxw=$fichero;
		$this->descomprimir_sxw($this->fichero_sxw, $this->desdirname, $this->desprefixname);
		$this->fichero_xml="$dirname_sxw/$prefixname_sxw/content.xml";
		$this->xml_parser=xml_parser_create();
		
//Puesto que el parse lo creamos desde un objeto debemos registrar la incidencia con xml_set_object

		xml_set_object($this->xml_parser,$this);
		
//Funciones de callback para manejar XML mediante SAX		

		xml_set_element_handler($this->xml_parser,"elemento_inicio","elemento_fin");
		xml_set_character_data_handler($this->xml_parser,"elemento_datos");
		
//Lo siguiente no funciona muy bien. Hay que hacer una gestión de lectura de fichero mejor

		if (!($fp = fopen($this->fichero_xml,"r")))
			{
			die ("Error de Entrada y Salida");
			}
		$this->pagina_inicio_OpenOffice();
		while ($datos = fread($fp,filesize($this->fichero_xml)))
			{
			if (!xml_parse($this->xml_parser,$datos,feof($fp)))
				{
				die ("Fallo en el XML");
				xml_error_string(xml_get_error_code($this->xml_parser));
				}
			xml_parser_free($this->xml_parser);
			}
		$this->pagina_fin_OpenOffice();
		}

//Imprime en pantalla una tabla con información de la versión

	function version()
		{
		echo ('<table width="100%" border="1" cellspacing="0" cellpadding="0">');
		echo ('<tr>');
		echo ('<td bordercolor="#000000" bgcolor="#999999">');
		echo ('<font color="#FFFFFF">');
		echo $this->version;
		echo ('</font>');
		echo ('</td>');
		echo ('</tr>');
		echo ('</font>');
		echo ('</table>');
		echo ('<p>');
		}
	function pagina_inicio_OpenOffice()
		{
		echo ("<table width=\"665px\" align=\"center\">");
		echo ("<tr>");
		echo ("<td>");
		}
	function pagina_fin_OpenOffice()
		{
		echo ("</td>");
		echo ("</tr>");
		echo ("</table>");
		}
//Descomprime un archivo OpenOffice en el directorio tmp/

	function descomprimir_sxw($fichero_sxw, $dirname_sxw, $prefixname_sxw)
		{

//Utiliza una librería para el tratamiento de ficheros ZIP

		require("pclzip.lib.php");
		if (!(file_exists("$dirname_sxw/$prefixname_sxw"))) mkdir("$dirname_sxw/$prefixname_sxw", 0777);
		copy($fichero_sxw,"$dirname_sxw/$prefixname_sxw/$prefixname_sxw.sxw.zip");

//Descomprimir el archivo OpenOffice

		$archive = new PclZip("$dirname_sxw/$prefixname_sxw/$prefixname_sxw.sxw.zip");
		$list = $archive->extract(PCLZIP_OPT_PATH, "", PCLZIP_OPT_ADD_PATH, "$dirname_sxw/$prefixname_sxw/");
		}

//Encuentra etiquetas de inicio en un documento XML
//$parser es el handler del parser, $name la etiqueta que se ha encontrado
//y $attributes un array con los atributos de esa etiqueta

	function meter_pila($attributes)
		{
		$this->pila[$this->puntero_pila]=$attributes;
		$this->puntero_pila++;
		}
	function sacar_pila()
		{
		$this->puntero_pila--;
		$attributes = $this->pila[$this->puntero_pila];
		return $attributes;
		}
	function elemento_inicio($parser,$name,$attributes)
		{

//Siempre que encontramos una etiqueta de inicio hacemos una copia de los atributos
//porque las etiquetas de fin no tienen y podemos necesitarlas. 

		//$this->ultimos_atributos=$attributes;
		$this->meter_pila($attributes);
		
//Se busca la etiqueta que coincide con el TOKEN y se ejecuta la acción pertinente		
	
		switch($name)
			{

//La etiqueta de estilos es la más importante, porque hay que guardarlos en array para posteriormente
//formatear los datos. Esto en DOM no pasa.

			case 'STYLE:STYLE':
				$this->guardar_estilo($attributes);
				break;
				
//Las propiedades del estilo también son necesarias				
				
			case 'STYLE:PROPERTIES':
				$this->guardar_estilo_propiedades($attributes);				
				break;

//Se ha encontrado un párrafo

			case 'TEXT:P':
				$this->parrafo_inicio($attributes);
				break;

//Se ha encontrado un grupo de caracteres distintos (de otro color, negrita, subrayado)

			case 'TEXT:SPAN':
				$this->caracter_inicio($attributes);
				break;

//Una tabla

			case 'TABLE:TABLE':
				$this->tabla_inicio($attributes);
				break;

//Una fila de una tabla

			case 'TABLE:TABLE-ROW':
				$this->columna_inicio($attributes);
				break;
			
//Una celda de una fila de una tabla			
			
			case 'TABLE:TABLE-CELL':
				$this->celda_inicio($attributes);
				break;
			
//Una imagen			
			
			case 'DRAW:IMAGE':
				$this->imagen_inicio($attributes);
				break;
				
//Tabulador

			case 'TEXT:TAB-STOP':
				$this->tabulador();
				break;
			}
		}
	
//Procesa las etiquetas de fin del archivo XML	
	function tabulador()
		{
		echo ("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
		}
	function elemento_fin($parser,$name)
	 	{
		$this->ultimos_atributos=$this->sacar_pila();
		switch($name)
			{
			case 'TEXT:P':
				$this->parrafo_fin($this->ultimos_atributos);
				break;
			case 'TEXT:SPAN':
				$this->caracter_fin($this->ultimos_atributos);
				break;
			case 'TABLE:TABLE':
				$this->tabla_fin();
				break;
			case 'TABLE:TABLE-ROW':
				$this->columna_fin();
				break;
			case 'TABLE:TABLE-CELL':
			    $this->celda_fin();
				break;
			}
		}
		
//Procesa los datos entre etiquetas 		
		
	function elemento_datos($parser,$cdata)
		{

//Se les pasa por el filtro utf8 para que se visualicen los acentos

		if (isset($cdata))
			{
			echo(utf8_decode($cdata));
			}
		else
			{
			echo ("&nbsp;");
			}
		}
		
//Genera el estilo de un párrafo en HTML y lo escupe en pantalla		
		
	function parrafo_inicio($attributes)
		{

//Se busca en los atributos de la etiqueta hasta encontrar el atributo TEXT:STYLE-NAME, 
//de donde se saca el nombre del estilo que tenemos guardado en array. Una vez se 
//obtiene el nombre se vierten los datos 

		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{
				case "TEXT:STYLE-NAME":
					if (isset($this->estilo["$value-ALIGN"]) || isset($this->estilo["$value-COLOR"]) || isset($this->estilo["$value-SIZE"]) || isset($this->estilo["$value-BOLD"]))
						{
						echo ("<p");
						if (isset($this->estilo["$value-ALIGN"]))
							{
							echo (" align=\"");
							echo $this->estilo["$value-ALIGN"];
							echo ("\"");
							}
						echo (">");
						/*
						echo ("<font");
						if (isset($this->estilo["$value-COLOR"])) 
							{
							echo (" color=\"");
							echo $this->estilo["$value-COLOR"];
							echo ("\""); 
							}
						if (isset($this->estilo["$value-SIZE"])) 
							{
							echo (" style=\"font-size: ");
							echo $this->estilo["$value-SIZE"];
							echo (";\"");
							}
						echo (">");*/
						$this->caracter_inicio($attributes);
						}
					else
						{
						echo ("&nbsp;");
						}
					break;
				}
			}
		}

//Genera el final del estilo Párrafo

	function parrafo_fin($attributes)
		{
		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{
				case "TEXT:STYLE-NAME":
					if (isset($this->estilo["$value-ALIGN"]) || isset($this->estilo["$value-COLOR"]) || isset($this->estilo["$value-SIZE"]) || isset($this->estilo["$value-BOLD"]))
						{
						$this->caracter_fin($attributes);
						echo "</p>";
						}
					break;
				}
			}
		}
	
//Genera el estilo de un grupo de caracteres de la misma forma que un Párrafo	
	
	function caracter_inicio($attributes)
		{
		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{
				case "TEXT:STYLE-NAME":
					if ((isset($this->estilo["$value-BOLD"]) && ($this->estilo["$value-BOLD"])<>"normal")) echo "<b>";
					if (isset($this->estilo["$value-ITALIC"])) echo "<em>";
					if ((isset($this->estilo["$value-UNDERLINE"])) && ($this->estilo["$value-UNDERLINE"])<>"none") echo "<u>";
					
					if (isset($this->estilo["$value-COLOR"]) || isset($this->estilo["$value-SIZE"]))
						{
						echo ("<font");
						if (isset($this->estilo["$value-COLOR"])) 
							{
							echo (" color=\"");
							echo $this->estilo["$value-COLOR"];
							echo ("\""); 
							}
						if (isset($this->estilo["$value-SIZE"])) 
							{
							echo (" style=\"font-size: ");
							echo $this->estilo["$value-SIZE"];
							echo ("\"");
							}
						echo (">");
						}
					break;
				}
			}
		}

////Genera el estilo final de un grupo de caracteres de la misma forma que un Párrafo

	function caracter_fin($attributes)
		{
		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{
				case "TEXT:STYLE-NAME":
					
					if ((isset($this->estilo["$value-BOLD"]) && ($this->estilo["$value-BOLD"])<>"normal")) echo "</b>";
					if (isset($this->estilo["$value-ITALIC"])) echo "</em>";
					if ((isset($this->estilo["$value-UNDERLINE"]) && ($this->estilo["$value-UNDERLINE"])<>"none")) echo "</u>";
					if (isset($this->estilo["$value-COLOR"]) || isset($this->estilo["$value-SIZE"]))
						{
						echo ("</font>");
						}
					break;
				}
			}
		}
		
//Genera el estilo de una tabla

	function tabla_inicio($attributes)
		{
		$this->columnas=1;
		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{				
				case "TABLE:STYLE-NAME":
				echo ("<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\" bordercolor=\"#000000\" width=\"");

//Estimación para escalar las tablas

				$resultado_parcial=floatval($this->estilo["$value-WIDTH"])*100/17.5;
				echo intval($resultado_parcial);
				echo("%\">");
				break;
				}
			}
		}

//Genera el estilo final de una tabla

	function tabla_fin()
		{
		echo ("</table>");
		}
	function columna_inicio()
		{
		$this->columnas = 1;
		echo ("<tr bordercolor=\"#000000\">");
		}
	function columna_fin()
		{
		echo ("</tr>");
		}
	function celda_inicio($attributes)
		{
		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{			
				case "TABLE:STYLE-NAME":
					echo ("<td");
					if (isset($this->estilo["$value-BACKGROUND-COLOR"]))
						{
						echo (" bgcolor=\"");
						echo $this->estilo["$value-BACKGROUND-COLOR"];
						echo("\"");
						}
					
//Se calcula el nombre de la tabla

					$nombre1=$value;
					$tamano1=strlen($nombre1);
					$nombre2=ereg_replace("^[a-zA-Z]+[1-9]+.","",$nombre1);
					$tamano2=strlen($nombre2);
					$estilo_actual=substr($nombre1,-$tamano1,-$tamano2);
					
//Se calcula la columna de la que sacar los datos de estilo_actual
					$nombre_columna="A";
					for ($numero_columna=1;$numero_columna<>$this->columnas;$numero_columna++)
						{
						$nombre_columna++;
						}

//$estilo_columna guarda por fin el estilo_actual

					$estilo_actual=$estilo_actual.$nombre_columna;
				
					if (isset($this->estilo["$estilo_actual-COLUMN-WIDTH"]))
						{
						echo (" width=\"");
						
//Estimación para escalar las tablas

						$resultado_parcial=floatval($this->estilo["$estilo_actual-COLUMN-WIDTH"])*100/17.5;
						echo intval($resultado_parcial);
						echo("%\"");
						$this->columnas_aux++;
						}		
					echo (" bordercolor=\"#000000\" height=\"20\"");
					echo (">");
					break;
				}
			}
		}
	function celda_fin()
		{
		$this->columnas++;
		echo ("</td>");
		}
		
//Genera la visualización de una imagen a partir de los datos guardados de su estilo 		
		
	function imagen_inicio($attributes)
		{
		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{
				case "DRAW:STYLE-NAME":
					$estilo_actual=$value;
					break;
				case 'SVG:WIDTH':
					$this->estilo["$estilo_actual-WIDTH"]=intval($value)*28*2;
					break;
				case 'SVG:HEIGHT':
					$this->estilo["$estilo_actual-HEIGHT"]=intval($value)*28*2;
					break;
				case 'XLINK:HREF':
					$this->estilo["$estilo_actual-IMAGEN"]="$this->desdirname/$this->desprefixname/".substr($value,1);
					break;
				}
			}
		//Ya hemos completado el estilo de la imagen con los datos interesantes
		//Ahora se muestra en pantalla
		echo ("<img src=\"");
		echo $this->estilo["$estilo_actual-IMAGEN"];
		echo ("\" width=\"");
		echo $this->estilo["$estilo_actual-WIDTH"];
		echo ("\" height=\"");
		echo $this->estilo["$estilo_actual-HEIGHT"];
		echo ("\" align=\"");
		echo $this->estilo["$estilo_actual-ALIGN"];
		echo ("\">");
		}

//Guarda un estilo en array con su propio nombre
		
	function guardar_estilo($attributes)
		{
		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{
				case "STYLE:NAME": 
				$this->estilo["$value-NAME"]=$value;
				$this->estilo_actual=$value;
				break;
				}
			}
		}
	
//Todos los estilos tienen una etiqueta que guarda las propiedades. El método siguiente 
//guarda los atributos de los estilos
	
	function guardar_estilo_propiedades($attributes)
		{
		$estilo_actual=$this->estilo_actual;
		while (list ($key,$value) = each ($attributes))
			{
			switch ($key)
				{
				case "FO:COLOR":
					$this->estilo["$estilo_actual-COLOR"]=$value;
					break;
				case "FO:BACKGROUND-COLOR":
					$this->estilo["$estilo_actual-BACKGROUND-COLOR"]=$value;
					break;
				case "FO:FONT-WEIGHT":
					$this->estilo["$estilo_actual-BOLD"]=$value;
					break;
				case "FO:FONT-STYLE":
					$this->estilo["$estilo_actual-ITALIC"]=$value;
					break;
				case "STYLE:WIDTH":
					$this->estilo["$estilo_actual-WIDTH"]=$value;
					break;
				case "STYLE:COLUMN-WIDTH":
					$this->estilo["$estilo_actual-COLUMN-WIDTH"]=$value;
					$columnas=$this->columnas;
					$this->estilo["$columnas-COLUMN-WIDTH"]=$value;
					$this->columnas++;
					break;
				case "STYLE:TEXT-UNDERLINE":
					$this->estilo["$estilo_actual-UNDERLINE"]=$value;
					break;
				case "FO:FONT-SIZE":
					$this->estilo["$estilo_actual-SIZE"]=$value;
				case "FO:TEXT-ALIGN":
					switch ($value)
						{
						case "start":
					    	$this->estilo["$estilo_actual-ALIGN"]="left";	
							break;
						case "end":
					    	$this->estilo["$estilo_actual-ALIGN"]="right";		
							break;
						case "justify":
					    	$this->estilo["$estilo_actual-ALIGN"]="justify";
							break;
						case "center":
					    	$this->estilo["$estilo_actual-ALIGN"]="center";
							break;
						}
					break;
				case 'STYLE:HORIZONTAL-POS':
					switch ($value)
						{
						case "center":
					    	$this->estilo["$estilo_actual-ALIGN"]="center";	
							break;
						}
					break;
				}
			}
		}
	}
?>
Return current item: Attachment_doc