La motivación de la pregunta se describió en la sección a continuación. Hay muchas formas de hacer que el texto esté en cursiva , por lo tanto, tal vez, haya más de un buen " algoritmo de intercambio de cursiva ". El problema revela algunas dificultades adicionales en un código XHTML, y el uso de la <i>
etiqueta, que debe ser equilibrado . Ejemplo:
<!-- original text: -->
<p id="p1"><i>Several more</i> Homo sapiens <i>fossils were discovered</i>.</p>
<!-- same text, swapping italics: -->
<p id="p2">Several more <i>Homo sapiens</i> fossils were discovered.</p>
Entonces, se ve así,
Se descubrieron varios fósiles más del Homo sapiens .
Se descubrieron varios fósiles más del Homo sapiens .
Introducción y discusión de algoritmos
Para la " solución de diseño ", el algoritmo más simple es verificar la font-style
propiedad CSS de todos los bloques de texto e invertirlos con jQuery:
$('#myFragment *').each(function(){
if ($(this).css('font-style')=='italic')
$(this).css('font-style','normal')
else
$(this).css('font-style','italic')
});
Pero este algoritmo no sobrevive a una prueba un poco más compleja,
<p id="p3"><b><i>F</i>RAGMENT <big><i>with italics</i> and </big> withOUT.</b></p>
El segundo algoritmo más simple es para una solución concreta , y se utilizó en la sección "Ejemplos". Tiene dos pasos:
- encierra el fragmento XHTML en cursiva;
- invertir abrir / cerrar etiquetas en cursiva (ej.
</i>
a<i>
).
Es decir, escribiendo con Javascript,
var s = '... a fragment of XHTML content ...';
s = '<i>'+
s.replace(/<(\/?)i>/mg,
function (m,p1){
return p1? '<i>': '</i>';
}
) +
'</i>';
Pero tampoco sobrevive a la segunda prueba, perdiendo el equilibrio de las etiquetas ... El algoritmo "corregido" se ejecuta (!), Pero no es portátil, ni rápido ni elegante. Se muestra aquí , y en la sección de ejemplos a continuación.
¡El punto!
Entonces la pregunta es,
Hay un algoritmo simple, bueno y genérico (utilizable en cualquier navegador y portátil a otros idiomas)? ¿Conoces otro "algoritmo de intercambio de cursiva"?
PD: "genérico" en el sentido de que incluso traduzco tu algoritmo a XSLT. El algoritmo debe producir código XHTML direccionalmente equilibrado (sin una caja negra intermedia como Tidy).
Motivaciones
Necesito portar el "algoritmo de intercambio de cursiva" a editores de texto, analizadores de servidores, etc. En todos los casos puedo "normalizar la entrada" (y salida) mediante XHTML estándar y <i>
etiqueta.
Estoy analizando el texto XHTML de libros en prosa y artículos científicos, exportados desde diferentes orígenes y estilos ... La mayoría de los textos se exportan como "texto normal", pero muchos títulos (por ejemplo, título de artículo, título de capítulo) y, a veces , un capítulo completo o un cuadro de texto completo (por ejemplo, resumen del artículo) están estilizados en cursiva. Todos estos "estilizados con cursiva" deben invertirse. Casos tipicos:
Transforme el original "cursiva de todos los capítulos" en "texto normal de todos los capítulos": vea este caso , donde en un libro de aproximadamente 300 páginas, 8 de los 25 capítulos deben invertirse.
Comillas en cursiva, resúmenes, etc. Vea este ejemplo . Necesita volver a la normalidad, pero sin perder las palabras de énfasis.
La escritura de nombres binomiales de especies , en textos científicos, generalmente está escrita en cursiva (o invertida, en una fuente diferente de la utilizada para "texto normal"). Cientos de títulos en cursiva (de artículos y secciones de artículos) de artículos exportados por XHTML deben invertirse en mi lugar de trabajo. PD: vea el ejemplo del comienzo de la pregunta ("Varios Homo sapiens más ...").
También necesito traducir el algoritmo genérico (¡de su respuesta!) A una biblioteca XSLT , donde no existe una "corrección de equilibrio de etiqueta".
Ejemplos
Implementando en Javascript y PHP un "algoritmo de intercambio de cursiva" no genérico . Una genérica necesita un "algoritmo de intercalación XML" general ... Aquí uso las correcciones del navegador (DOM) y Tidy, como alternativa a la "intercalación".
Javascript
Se ejecuta con entradas complejas (!). Ilustrando, mediante una implementación de jQuery :
var s = $('#sample1').html(); // get original html text fragment
// INVERSION ALGORITHM: add and remove italics.
s = "<i>"+
s.replace(/<(\/?)i>/mg,
function (m,p1){
return p1? '<i>': '</i>';
}
) +
"</i>"; // a not-well-formed-XHTML, but it is ok...
$('#inverted').html(s); // ...the DOM do all rigth!
// minor corrections, for clean empties:
s = $('#inverted').html();
s = s.replace(/<([a-z]+)>(\s*)<\/\1>/mg,'$2'); // clean
s = s.replace(/<([a-z]+)>(\s*)<\/\1>/mg,'$2'); // clean remain
$('#inverted').html(s);
// END ALGORITHM
alert(s);
PHP, con Tidy
Lo mismo de Javascript, "traducido" a PHP: la traducción natural es usar DOMDocument()
class y loadHTML
/ saveXML
methodos, pero lo que tiene el mismo comportamiento que los corresponsales del navegador es la tidy
clase . Muestra los mismos resultados (!)
$sample1='<b><i>O</i>RIGINAL <big><i>with italics</i> and </big> withOUT</b>';
$inverted = '... inverted will be here ...';
echo $sample1;
// Tidy correction
$s = $sample1; // get original html text fragment
// INVERSION ALGORITHM: add and remove italics.
$s = "<i>".
preg_replace_callback('/<(\/?)i>/s', function ($m){
return $m[1]? '<i>': '</i>';}, $s) .
"</i>"; // a not-well-formed-XHTML, but it is ok...
$config = array('show-body-only'=>true,'output-xhtml'=>true);
$tidy = new tidy;
$tidy->parseString($s, $config, 'utf8');
$s = $tidy; // ... because Tidy corrects!
// minor corrections, for clean empties:
$s = preg_replace('/<([a-z]+)>(\s*)<\/\1>/s', '$2', $s); // clean
$s = preg_replace('/<([a-z]+)>(\s*)<\/\1>/s', '$2', $s); // clean remain
// END ALGORITHM
echo "\n\n$s";
fuente
Respuestas:
Actualización (18 de junio de 2013): uso de esta respuesta para explicar algoritmos y resumir conclusiones.
Acerca de las soluciones alternativas de "solución de diseño" de jQuery.
Después del comentario de @Wilbert, adapté el "algoritmo más simple", para evitar el comportamiento dinámico del
check .prop()
, que cambia con la.each()
iteración, eliminando elelse
. Después de toda la iteración, se resuelve un "cursiva principal". Ver aquí o el código a continuación.Otra forma de lidiar con el comportamiento dinámico es verificar una propiedad estática
prop('tagName')
, que no cambia. Ver aquí o el código a continuación.Necesita más pruebas y necesita un análisis final para cambiar las propiedades de estilo a
<i>
etiquetas concretas . Para aplicar el algoritmo dos veces, necesitamos un poco de cuidado.Solución de diseño
¡Esta no es una solución para la presente pregunta, pero produce algunas buenas pistas, y es la mejor solución (¡al menos la más pequeña!) Para el "problema de diseño".
El
toggleClass()
método se puede utilizar para cambiar de una "clase en cursiva" a una "clase de texto normal". Ver aquí o el código a continuación.Y podemos aplicar este pequeño algoritmo dos veces, y tantas veces como queramos ... ¡Es una buena solución! Pero no es un "algoritmo XML de reescritura", el CSS es una clave aquí :
... Entonces, para un algoritmo que transforma
<i>
etiquetas, el problema aún está abierto ...Solución concreta
Una "solución 100%, en puro XSLT1" (¡probada en muchos casos!) Basada en una adaptación de @ DanielHaley's . Es una efectiva
<i>
transformación de etiquetas.Esquema como un "algoritmo de unidad por evento" en un proceso de copia:
eliminar
i
etiquetas: copie cualquier cosa de "<i>
cosa</i>
" como " cosa ".incluir
i
etiquetas: copie cualquier texto como "<i>
texto</i>
", cuando el texto no esté en un contexto de padres en cursiva. PD: el texto es un nodo terminal del árbol DOM.Conclusiones
Las "soluciones de diseño" son buenas para los editores de texto , pero utilizan algunos trucos y soluciones no rigurosas (sin importar las superposiciones, el rendimiento, etc.). Para el proceso XML tenemos que lidiar con la
<i>
transformación de etiquetas ... Entonces, los lenguajes naturales para expresar el algoritmo son XSLT o xQuery.El algoritmo implementado con XSLT muestra las necesidades del marco:
el selector ancestro (padre, abuelo, etc.), para verificar si es o no un "contexto en cursiva";
el
text()
acceso de nodo de texto (DOM );eliminar e incluir la
i
etiqueta.Entonces, podemos ver los problemas con cada marco.
DOM (el marco estándar W3C): el
DOMDocument::renameNode()
, para el ítem 3, aún no está implementado (ver PHP, Javascript, etc.).jQuery: no tiene una función convenientes para el artículo 2, ver esta respuesta .
XSLT: lo mejor para expresar el algoritmo, pero no está disponible en ningún contexto como Javascript.
Yo (¡o por favor!) Intentaré expresar el algoritmo XSLT con métodos de "DOM2 puro". Esa versión DOM será el "algoritmo genérico" ... Bueno: si la traducción es válida solo para DOM3 (usando renameNode y otros trucos), la conclusión por ahora es que "NO hay algoritmo genérico / traducible".
fuente
Intento de XSLT desde https://stackoverflow.com/a/17156452/317052 ...
No estoy seguro de si esto cubriría todos los casos, pero podría hacer esto:
Entrada XML
XSLT 1.0
Salida XML
Entrada procesada
Se descubrieron varios fósiles más del Homo sapiens .
Se descubrieron varios fósiles más del Homo sapiens .¡Déjame solo!
O RIGINAL con cursiva y sin
Salida procesada
Se descubrieron varios fósiles más del Homo sapiens .
Se descubrieron varios fósiles más del Homo sapiens .¡Déjame solo!
O RIGINAL con cursiva y sin
fuente
Yo simplemente:
<i>
a</i>
s</i>
a<i>
s<i>
al principio</i>
al finalEntonces
fuente
<b><i>O</i>RIGINAL <big><i>with italics</i> and </big> withOUT</b>
... produce código umbalanced (¡prohibido!) Y bloques vacíos .<i><b></i>O<i>RIGINAL <big></i>with italics<i> and </big> withOUT</b></i>
puede no ser bonito pero funciona en todos los navegadores<i><b></i>
no lo es, y TODA LA DISCUSIÓN AQUÍ se trata de "un algoritmo que produce resultados equilibrados".