<?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 (" ");
}
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 (" ");
}
}
//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 (" ");
}
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;
}
}
}
}
?>