Ya la terminé y funcion Ok, pero resulta que las fuentes de los datos son bastante "sucias": unas listas hechas por los juzgados con MS Word y cada tanto tienen alguna pifiada.
Entonces quiero agregar varias reglas de validación para que si aparece algo raro, devuelva false y aborte.
La primera para que no haya etiquetas sin cerrar no fue díficil, pero ahora quiero verificar que no exista ninguna etiqueta <TD> o </TD> fuera de <TR>...</TR> y que cada <TD> y <TR> tenga su par.
Si bien podría hacerlo con varias líneas de código y diversas funciones imagino que debe haber alguna manera más eficiente de hacer esto con PCRE.
Puede que sea una bobada pero hasta ahora no encontré la manera de hacerlo en una o dos líneas.
Acá van las dos funciones por si a alguien le sirve, o mejor aún si pueden sugerirme cómo mejorar:
Código PHP:
function table_to_array($tabla, $encabezados=false) {
/*BUSCAR LA FORMA DE VALIDAR EL HTML, ESPECIFICAMENTE QUE LAS FILAS
Y COLUMNAS ESTÉN BIEN FORMADAS*/
if (!preg_match("/^\<TABLE.*\<\/TABLE\>$/is",$tabla)) {
$msgerror = "no es una tabla";
return false;
}
$patrones_tabla[0]= "/\<TR.*\>/iU";
$patrones_tabla[1]= "/\<TD.*\>/iU";
$reemplazos_tabla[0] = "#fila#";
$reemplazos_tabla[1] = "#columna#";
$tabla = preg_replace($patrones_tabla,$reemplazos_tabla, $tabla);
$tabla = strip_tags($tabla);
$filas = explode("#fila#",$tabla);
array_shift($filas);
if ($encabezados) {
$rotulos = explode("#columna#",$filas[0]);
array_shift($rotulos);
for($c=0;$c<sizeof($rotulos);$c++) {
$rotulos[$c] = trim(strtolower($rotulos[$c]));
}
array_shift($filas);
for ($f = 0; $f<sizeof($filas);$f++) {
$unafila = explode("#columna#",$filas[$f]);
array_shift($unafila);
for ($c=0;$c<sizeof($rotulos);$c++) {
$salida[$f][$rotulos[$c]]=$unafila[$c];
}
}
} else {
for ($f = 0; $f<sizeof($filas);$f++) {
$unafila = explode("#columna#",$filas[$f]);
array_shift($unafila);
for ($c=0;$c<sizeof($unafila);$c++) {
$salida[$f][$c]=$unafila[$c];
}
}
}
return $salida;
}
function validar_html($codigo) {
/*Controla que todas las etiquetas html estén cerradas '<>'
*/
if (preg_match("/\<[^\>]*\</",$codigo)) {
//encuentra '<' sin cerrar
return false;
}
if (preg_match("/\>[^<]*\>/",$codigo)) {
//encontró > sin previa apertura o dicho de otra forma dos > sin un < en el medio
return false;
}
if (preg_match("/^[^<]*\>/", $codigo)) {
//se encontró un > antes de un <
return false;
}
if (preg_match("/\<[^\>]*$/", $codigo)) {
//se encontró un < sin cerrar antes del final
return false;
}
return true;
}