Limpiar el EPUB

Encontrar y corregir problemas en los archivos EPUB

En los documentos EPUB, no se pueden detectar algunos problemas con los métodos normales de validación. Siempre y cuando el documento valida como un XML bien formado y sigue el estándar de EPUB, puede parece correcto, pero existe la posibilidad de que no pueda leer correctamente en un e-Reader. Los ejemplos incluyen saltos de párrafos, mala numeración de páginas, y errores de ortografía causados por el escaneo de OCR. Pero los errores se pueden ver y corregir mediante dos métodos: con el EPUB editor de Sigil y con PHP en combinación con SimpleXML y las bibliotecas Enchant. Las expresiones regulares proporcionan la clave para un procesamiento eficiente.

Colin Beckingham, Writer and Researcher, Researcher

Colin Beckingham es un investigador autónomo, escritor, y programador que vive en la parte este de Ontario, Canadá. Con títulos de la Universidad de Queen, Kingston, y la Universidad de Windsor, ha trabajado en una gran variedad de campos incluyendo la banca, la horticultura, las carreras de caballos, la enseñanza, la administración pública, el comercio minorista y los viajes y el turismo.Autor de aplicaciones de base de datos y numerosos periódicos, revistas y artículos online, sus intereses de investigación incluyen la programación de open source, VoIP, y aplicaciones de control de voz en Linux.Usted puede encontrar a Colin en colbec@start.ca.



12-03-2012

El formato EPUB es un eficiente método de presentar documentos. Su estructura XML garantiza que los componentes de los documentos estén en su lugar y se mostrarán razonablemente bien en una amplia variedad de dispositivos. Para una introducción a EPUB, ver el artículo de Liza Daly en Recursos.

Acrónimos de uso frecuente

  • GUI: Interfaz gráfica de usuario
  • OCR: Reconocimiento de carácter óptico
  • HTML: Lenguaje de marcado de hipertexto
  • WYSIWYG: Lo que ves es lo que obtienes
  • XML: Lenguaje de Marcación Extensible

Estos documentos pueden fallar en dos niveles:

  • En el nivel fundamental, donde la marcación XML o el contenido está roto
  • Más sutilmente — a un nivel que la verificación de XML no se puede detectar

Para el problema anterior, donde el EPUB está internamente roto, se puede utilizar el proyecto EpubCheck (ver Recursos donde encontrará un enlace).El resto de este artículo analiza el segundo tipo de problema, el cual puede ser una molestia para los lectores.

El estricto control que impone XML sólo va más allá.XML permite de buen grado una serie de errores que, aunque no lo suficientemente graves como para causar un error de software, no obstante, dificulte una lectura fluida. Es fácil de ver cómo se producen estos errores — si un editor utiliza OCR en una página impresa para transferirlo a un formato de texto, entonces se mantienen todas las singularidades de la página impresa, incluidos los errores derivados de la incompatibilidad de la fuente. En una situación comercial, los editores revisan el resultado a mano para generar una edición pulida, pero donde el producto está proyectado para una distribución de fuente libre y abierta, los editores no pueden absorber estos costos con la misma facilidad. Así que lo que termina en e-Reader es bueno pero no tan bueno como podría ser.Los ejemplos incluyen párrafos rotos, páginas en blanco, extrañas numeraciones de páginas, y errores ortográficos.

Desde el punto de vista del desarrollador, el desafío está en cómo se pueden abordar estos problemas utilizando la estructura de la EPUB. Este artículo analiza cómo se puede utilizar la EPUB editor de Sigil para hacer frente a algunos de ellos y utilizar PHP en combinación con SimpleXML y las bibliotecas ortográficas para resolver muchos otros.

Saltos de párrafos y páginas en blanco

Utilizar un salto de párrafo como ejemplo de un problema secundario.En la marcación HTML, este problema aparece como:

<p>This is where my paragraph begins, hits the end of a physical page here</p>
<div class="newpage" id="page-12"></div>
<p>and then continues from the top of the next physical page,
     finally coming to an end here.</p>

El escáner ha leído hasta el final de una página, pone en una etiqueta de párrafo independientemente si se aplica para garantizar que la página está sintácticamente completa, entonces empieza en la parte superior de la página siguiente, asegurándose de que comienza con un nuevo párrafo —una vez más, si es apropiado o no.Hace que se complete el código, pero deja párrafos incompletos debido a las secciones huérfanas. En el e-Reader, el usuario puede que vea las dos secciones en la misma página del dispositivo sin que aparezca el marcador de página, pero las secciones del párrafo las separa como si fueran párrafos independientes.

De igual manera, considera las páginas en blanco:

<div class="newpage" id="page-128"></div>
<p></p>
<div class="newpage" id="page-129"></div>

¿Existe realmente la página 129 en el fragmento anterior? Podría ser importante el preservarla en blanco, pero de lo contrario, no es conveniente pasar dos páginas cuando sólo una debería ser necesaria.

Los errores ortográficos son un tipo de problema diferente donde se comparan dos listas de palabras distintas en vez de buscar patrones complejos. Este problema se trata por separado por medio de métodos de scripting.


Sigil

Sigil (ver Recursos para la web site y las páginas de soporte) es una EPUB editor Lo que se ve es lo que se obtiene que puede encontrar tipos de errores de coincidencia de patrones y permitir que los programadores los corrijan. Consulte la sección del tema Barra lateral de expresión regular para una rápida introducción a las expresiones regulares, y vea Recursos para una información más detallada.

Expresiones regulares

Las expresiones regulares ofrecen una forma eficaz de buscar y reemplazar textos mediante técnicas de coincidencia de patrones.La sintaxis es concisa, por lo que es necesario tener cuidado para evitar efectos no deseados.

Un ejemplo de una expresión regular es [^.]</p>, la cual busca un final de la etiqueta de párrafo que no está precedida por un periodo. Esto puede que sea o no sea un problema.

En esta expresión regular, los corchetes ([]) abarcan un grupo de caracteres en los que sólo uno puede aplicarse, el símbolo de intercalación (^) significa Ninguno de los siguientes caracteres, y el periodo (.) dentro del grupo representa a ellos mismos, al igual que el resto de los símbolos fuera de los corchetes.

Consulte Recursos para un comentario más profundo de esta útil herramienta.

Sigil puede que no está disponible desde su repositorio Linux® , pero está disponible como un binario precompilado o como archivos de origen.Una vez en el GUI, hacer clic en File > Open para abrir su EPUB directamente.El hacerlo extrae el EPUB y muestra un directorio de los archivos de componentes de la izquierda, revela un panel del navegador a la derecha, en el cual se puede mostrar el contenido de los archivos individuales, como aparecen en el e-Reader o como aparecen en el código marcado. Este último punto es un dispositivo esencial para encontrar y corregir problemas.

Elija uno de los archivos HTML que contiene su EPUB y haga doble clic en él para abrirlo en la ventana del navegador. A continuación, haga clic en View > Code View para mostrar el código detrás del archivo.Todas las etiquetas deberían ser ahora visibles.

Supongamos que quiere usted encontrar fragmentos de párrafo huérfanos.El criterio que se busca es </p> etiquetas de final del párrafo que no están precedidas por un carácter normal de fin de la oración. El carácter más común es el periodo.Sigil proporciona una función de búsqueda (Edit > Find), el modo de búsqueda normal, le permite encontrar series como .</p>, pero no le ayuda a encontrar el final del párrafo que no tiene un período antes que él. Para ello, es necesario el modo de búsqueda de expresión regular, el cual aparece al hacer clic en More. Vaya a la parte superior del código en la ventana del navegador, una vez allí siga estos pasos:

  1. Seleccione Down para la dirección.
  2. Seleccione Regular expression para el modo de búsqueda.
  3. Escribir [^.]</p> como su cadena de caracteres Find what .
  4. Haga clic en Find Next.

Este proceso debería encontrar lo que está buscando, en caso de que exista.Si no se encuentran coincidencias, es posible que quiera crear uno temporalmente sólo para verificar que la función de búsqueda funciona.

Después de utilizar esta técnica por un periodo de tiempo, pronto se dará cuenta de que los párrafos pueden terminar legítimamente con caracteres que no sean períodos.Usted encontrará que las dobles comillas ("), signos de exclamación (!), signos de interrogación (?), y quizás algunos otros caracteres se ajustan a los requisitos de una oración completa. El permitir esto no es un problema con las expresiones regulares. Ya que los corchetes indican un grupo, si se cambia el Find what hasta [^.?!"]</p>, la búsqueda acepta como normal cualquier cosa que tenga un período, signo de interrogación, signo de exclamación o signo de dobles comillas al final de un párrafo y marca como erróneo todo lo demás.

Otros signos indicadores de un salto de párrafo podrían ser aquellos que comienzan con <p> seguido de un carácter alfabético minúsculo. La versión de expresión regular de esto sería <p>[a-z].. Otra útil es <p>[0-9]., la cual busca párrafos que comienzan con números. Este signo puede ser válido cuando el escáner ha seleccionado un número de página que en un contexto de e-Reader que podría ya no ser relevante.

El cómo usted decide arreglar uno de estos errores es otra cuestión. Si un marcador de página separa las dos partes, se puede mover el marcador a antes o después del párrafo verdadero y volver a unir las dos partes para hacer un único párrafo. La numeración de las páginas se aproxima entonces, pero no es del todo exacta.

La búsqueda de marcadores de página es un proceso parecido.De nuevo, utilizando la opción de expresión regular si el Find what está en la página-[0-9]+, el editor busca cualquier cadena de caracteres que comience con los caracteres literales p, a, g, e, y en el dash seguido por al menos uno y quizás varios caracteres numéricos en un rango de cero a nueve.

Una separación interesante que usted puede encontrar fácilmente, es donde una palabra, párrafo, y página están todas separadas al mismo tiempo. La versión de impresión indica la separación con un guión, que es fácilmente visible y se busca en la vista de código:

<p>This is where my paragraph begins, hits the end of a phys-</p>
<div class="newpage" id="page-12"></div>
<p>ical page and then continues from the top of the next physical page, 
     finally coming to an end here.</p>

En este caso, una búsqueda normal global utiliza la cadena de caracteres Find what de -</p> debería seleccionarlos muy rápidamente.


Revisar los números de página

Aunque se puede utilizar Sigil para encontrar y revisar saltos de página y numeración, en un documento de más de 100 páginas, el hacerlo puede resultar aburrido. Una forma más fácil es iterar a través de los documentos con PHP y revisar la numeración.

El script en el Listado 1 encuentra y revisa las páginas HTML y se ejecuta a través de los saltos de página. Encuentra el número de la primera página, que es muy a menudo diferente al de la página 1, y verifica que cada página que sigue es un incremento de la primera página. Aunque la prueba de numeración de las páginas es bastante simple, es un ejemplo de cómo utilizar el archivo OPF para encontrar y examinar el componente HTML.

Listado 1. Verificación de la página EPUB con PHP y SimpleXML
<?php
/* epub is a zipped package containing many files
  the file "content.opf" contains the pointers to the constituent files
  inside content.opf you have

  package (root)
    -> manifest
      -> item
          which we need to filter for media-type="application/xhtml+xml"
          and to check these are real text pages, not just full page images

  these are the text chapters which need to be checked one by one
*/
$firstpage = 0;
$oldpage = 0;
// look for the text to be checked
$opf_file = "./OEBPS/content.opf";
if (!file_exists($opf_file)) {
  //cleanup();
  die("Cannot find the OPF file\n");
} else {
  echo "Found it!\n";
  $xml = simplexml_load_file($opf_file);
  // get the manifest items
  foreach ($xml->manifest->item as $mi) {
    if ($mi['media-type']=='application/xhtml+xml') {
      echo "Found ".$mi['href']."\n";
      if (substr($mi['href'],0,4) == 'part') {
          echo "Page number check in document ".$mi['href']."\n";
          echo scan_chap("./OEBPS/".$mi['href']);
      }
    }
  }
}
function scan_chap($chap) {
global $firstpage, $oldpage;
  echo "Trying to page num check section $chap \n";
  if (!file_exists($chap)) {
    echo "Cannot find the chapter $chap\n";
  } else {
    echo "Found it!\n";
    $xml = simplexml_load_file($chap);
    //$i = 0;
    foreach ($xml->body->div->div as $pagnumdiv) {
      if ($pagnumdiv["class"]=='newpage') {
          echo $pagnumdiv["id"]."\n"; $page = (int) substr($pagnumdiv["id"],5);
          if ($firstpage == 0) {
          $firstpage = $oldpage = $page;
          } else {
          if ($page != $oldpage+1) echo "Problem at page after $oldpage\n";
          $oldpage++;
          }
      }
    }
  }
  return "Done...\n";
}
?>

El código establece en primer lugar las variables globales para el número de la primera página lógica encontrada (la establece una vez al principio del bucle) y el número de la página anterior seleccionada (que cambia con cada iteración). A continuación declara el nombre del archivo OPF, busca ese archivo, y — si no lo puede encontrar—finaliza con un error. Si se encuentra el archivo, el script abre el archivo como un objeto XML y busca los nombres de los archivos mencionados en el manifiesto que parecen ser HTML usando el atributo media-type . En este documento EPUB en particular, algunos archivos HTML contienen sólo una imagen de la página completa y por lo tanto se puede ignorar. Los nombres de archivos de estas páginas contienen la cadena de caracteres leaf; el resto de archivos que contienen el texto extendido tienen una etiqueta de componente . Los filtros de código que sacan utilizan subseries.

Ahora que usted conoce el nombre del archivo, puede leer este archivo en su propio objeto simpleXML .Internado a través de etiquetas <div> y filtrando aquellas que tienen un atributo de clase newpage, usted puede encontrar el valor del atributo de id que contiene el número de página.Es necesario dejar que el libro le diga el número de la primera página porque a menudo no es la página 1, y una vez se ha almacenado este valor en la variable de la primera página global, usted puede continuar y predecir el número de la siguiente página. Si no es el número esperado, el script genera un error y continúa la corrección.

Este script no trata de realizar cambios en el texto. Se limita a marcar lo que cree que podría necesitar su atención.


Corrección de la ortografía con PHP, XML, y Enchant

La ortografía es un problema diferente.En este caso, en realidad se trata de eventos como Upon, el cual OCR ha leído como TJpon o IJpon, que es parecido pero no es correcto.Que podría venir como una serie de alternativas, y la rutina de ortografía lo ve tan extraño que las sugerencias que ofrece no se parecen ni resultan de utilidad.

Una rutina ortográfica examina las palabras una por una y las compara con una lista estándar conocida, indicando aquellas que no coinciden, haciendo sugerencias, y permitiéndole realizar cambios. Sigil puede hacer sustituciones de series específicas a través de diversos documentos en el paquete de EPUB, pero se necesita la potencia de un motor de scripting como PHP, Perl, Python, etc., junto con bibliotecas especializadas, para un control más detallado.

Las nuevas versiones de PHP contienen ahora los ganchos necesarios no sólo para profundizar en los archivos XML y HTML utilizando SimpleXML, sino también para el uso de la biblioteca del gestor ortográfico de Enchant. Enchant puede administrar múltiples listas ortográficas de base diferentes. Lo que ayuda a diferenciar la ortografía del inglés del Reino Unido con la del inglés americano, por ejemplo.

El script en El Listado 2 examina cada uno de los archivos de manifiesto por separado utilizando el mismo método que en El Listado 1, esta vez revisando párrafo por párrafo y palabra por palabra comprobando la ortografía con la lista conocida. Utiliza el mismo método de iteración a través de los archivos de componente HTML que en el Listado 1 y añade las instrucciones necesarias para acceder a los diccionarios.

Listado 2. Correcciones ortográficas de las páginas EPUB con PHP, SimpleXML, y Enchant
<?php
  // spell check an epub
/* epub is a zipped package containing many files
  the file "content.opf" contains the pointers to the constituent files
  inside content.opf we have

  package (root)
    -> manifest
      -> item
          which we need to filter for media-type="application/xhtml+xml"
          and to check these are real text pages, not just full page images

  these are the text chapters that need to be checked one by one

  Acknowledgment: Some of the dictionary-related code
  was copied from the PHP Enchant manual page

*/
// set up console for input
$console = fopen("php://stdin","r");
// set up enchant (from PHP manual)
$tag = 'en_CA';
$r = enchant_broker_init();
$bprovides = enchant_broker_describe($r);
echo "Current broker provides the following backend(s):\n";
print_r($bprovides);
$dicts = enchant_broker_list_dicts($r);
print_r($dicts);
if (enchant_broker_dict_exists($r,$tag)) {
    $d = enchant_broker_request_dict($r, $tag);
    $dprovides = enchant_dict_describe($d);
    echo "dictionary $tag provides:\n";
} else {
  cleanup();
  die ("Cannot set up the spell checker\n");
}
// look for the text to be checked
$opf_file = "./OEBPS/content.opf";
if (!file_exists($opf_file)) {
  cleanup();
  die("Cannot find the OPF file\n");
} else {
  echo "Found it!\n";
  $xml = simplexml_load_file($opf_file);
  foreach ($xml->manifest->item as $mi) {
    if ($mi['media-type']=='application/xhtml+xml') {
      echo "Found ".$mi['href']."\n";
      if (substr($mi['href'],0,4) == 'part') {
          echo "Need to spell check ".$mi['href']."\n"; 
          echo scan_chap("./OEBPS/".$mi['href']);
      }
    }
  }
}
function cleanup() {
global $d, $r;
  enchant_broker_free_dict($d);
  enchant_broker_free($r);
}
function scan_chap($chap) {
  echo "Trying to spell check section $chap \n";
  if (!file_exists($chap)) {
    echo "Cannot find the chapter $chap\n";
  } else {
    echo "Found it!\n";
    $xml = simplexml_load_file($chap);
    $i = 0;
    foreach ($xml->body->div->p as $para) {
      echo $para."\n";
      // need to spell check the contents of $para
      spell_check(trim($para));
      $i++;
      if ($i > 5) break;
    }
  }
  return "Done...\n";
}
function spell_check($para) {
global $console, $d;
  $para = str_replace("  "," ",$para);
  $para = str_replace(".","",$para);
  $para = $para." ";
  echo "Checking text : $para\n";
  $start = 0;
  while ($pos !== false) {
    $pos = strpos($para," ",$start);
    echo "Found $pos\n";
    if (!$pos) break;
    $len = $pos-$start;
    $theword = substr($para,$start,$len);
    // tidy up theword which may contain punctuation
    $punc = array(':',';',',','"','?','!'); $theword = str_replace($punc,"",$theword);
    //
    if ((strlen($theword) > 0) and (!is_numeric($theword))) {
      if ($wordcorrect = enchant_dict_check($d, $theword)) {
          echo "$theword is OK!\n";
      } else {
          $suggs = enchant_dict_suggest($d, $theword);
          echo "Suggestions for <$theword>:\n";
          //print_r($suggs);
          $max = 5;
          foreach ($suggs as $k=>$sugg) {
            echo "$k => $sugg\n";
            if ($k > $max) break;
          }
          $inp = fgets($console,1024);
      }
    }
    $start += $len+1;
  }
}
?>

En este código, se empieza por declarar un puntero de archivo a una entrada estándar para que usted pueda obtener información interactiva desde el teclado durante el proceso de corrección ortográfica. La sección siguiente establece la conexión con los diccionarios. Observe que la variable tag que se indica en-CA, la cual en este ejemplo pone una preferencia en el inglés canadiense. El resultado es que el corrector elige color sobre color, reconocimiento sobre reconocimiento, y así sucesivamente.Una configuración más estándar de la etiqueta es es-es. Una vez conectado el diccionario, realiza la misma búsqueda de archivos de texto HTML, como en el Listado 1 , pero esta vez, en lugar realizar la búsqueda por etiquetas de número de página <div> , busca párrafos con textos reales.

Antes de realizar la corrección ortográfica actual, el script limpia el texto de párrafo para hacerlo más manejable eliminando los espacios largos y eliminando los periodos y las comas ya que el objetivo es examinar palabra por palabra. Entonces, la corrección ortográfica real comienza pasando de una palabra a otra en el párrafo, ignorando las palabras que son números y comparando la palabra con el diccionario. Cuando el diccionario no contiene la palabra, el script sugiere palabras que pudieran ser un mejor sustituto. En este caso, el script sólo presenta las primeras cinco alternativas. El script se para en cada palabra con un problema y espera la entrada del usuario desde el teclado. En este momento, se puede añadir código para cambiar, ignorar una vez, ignorar para la sesión, y así sucesivamente.


Conclusión

Tanto los scripting de Sigil y PHP con XML y las bibliotecas de ortografía son herramientas útiles para encontrar y corregir errores que no se pueden detectar por medio de rutinas de verificación de EPUB normales. Si estos errores secundarios son realmente errores o simplemente inconvenientes cosméticos menores que dependen del contexto en el cual se está utilizando el documento y la capacidad del lector de hardware y su propio software para resolver estos problemas por el camino.

Recursos

Aprender

  • Build a digital book with EPUB (Liza Daly, developerWorks, actualizado en enero del 2011, publicado en noviembre del2008): Lea una introducción a EPUB y una lista de los recursos EPUB.
  • Know your regular expressions, (Michael Stutz, developerWorks, junio del 2007): Echar un vistazo a las expresiones regulares en los sistemas UNIX® .Descubra las herramientas y técnicas disponibles que pueden ayudarle a aprender a construir expresiones regulares para los diversos programas y lenguajes.
  • Más artículos de este autor (Colin Beckingham, developerWorks, marzo de 2009-actual): Lea artículos sobre XML, reconocimiento de voz, XHTML, PHP, SMIL, y otras tecnologías.
  • ¿Principiante en XML? Obtenga los recursos que necesita para aprender de XML.
  • Área XML en developerWorks: Encuentre los recursos que necesita para mejorar sus habilidades en el XML arena, incluyendo DTDs, esquemas y XSLT. Consulte la sección del tema Biblioteca técnica XML para una amplia gama de artículos técnicos y consejos, tutoriales, normativas e IBM Redbooks.
  • Certificación IBM XML: Conozca cómo puede usted convertirse en un Desarrollador Certificado IBM en XML y en tecnologías relacionadas.
  • Eventos técnicos y webcasts de developerWorks: Manténgase actualizado(a) con la tecnología en estas sesiones.
  • developerWorks en Twitter: Únase hoya para seguir los tweets developerWorks.
  • developerWorks podcasts: Escuche interesantes entrevistas y discusiones para desarrolladores de software.
  • Demostraciones on demand de developerWorks: Observe demostraciones que van desde la instalación de productos y demostraciones de configuración para principiantes, hasta funcionalidades avanzadas para desarrolladores experimentados.

Obtener los productos y tecnologías

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Linux
ArticleID=800879
ArticleTitle=Limpiar el EPUB
publish-date=03122012