Quizás haya una forma más fácil de usar expresiones regulares en Java, pero yo no la encuentro. Usarlas en JavaScript, Python o Ruby es de las cosas que hacen atractivos estos lenguajes, pero en Java cuesta hacer natural lo natural.
Mi problematica es que tengo un servicio que retorna contenido HTML, y necesito dos cosas:
1. Saber cuantos caracteres del contenido pertenecen a TAGS HTML.
2. Retornar el contenido sin HTML, o sea en texto plano.
Por ejemplo, del texto:
"Presione <b><a href="javascript:void(0)">Aqui</a></b>..."
Debo retornar ["Presione Aqui", 40]. (40 es la cantidad de caracteres dentro de los tags).
Luce sencillo a simple vista, parsear el texto en busca de patrones que se corresponden con TAGS HTML substituyendo el patrón por un caracter blanco para eliminar los TAGS y contando el length de cada patrón devuelto. O sea se hace evidente el uso de Expresiones Regulares.
A continuación mi solución para que noten lo complicado que se hace programar con expresiones regulares en Java. Si alguien encuentra una forma más natural por favor no dude en enviarmela a través de un comentario.
…
Primero un contenedor de expresiones regulares compiladas
// regular expression Patterns (HTML TAGS) container
private static final Pattern[] HTML_TAG_REXP;
// init
static {
HTML_TAG_REXP = new Pattern[] {
Pattern.compile("<(a|A).*?>"),
Pattern.compile("</(a|A)>"),
Pattern.compile("<(b|B).*?>"),
Pattern.compile("</(b|B)>"),
Pattern.compile("<(i|I).*?>"),
Pattern.compile("</(i|I)>"),
Pattern.compile("<(p|P).*?>"),
Pattern.compile("</(p|P)>"),
Pattern.compile("<(img|IMG).*?>"),
Pattern.compile("</(img|IMG)>"),
Pattern.compile("<(stong|STRONG).*?>"),
Pattern.compile("</(strong|STRONG)>"),
Pattern.compile("<(h1|H1).*?>"),
Pattern.compile("</(h1|H1)>"),
Pattern.compile("<(h2|H2).*?>"),
Pattern.compile("</(h2|H2)>"),
Pattern.compile("<(h3|H3).*?>"),
Pattern.compile("</(h3|H3)>"),
};
}
Al compilarlas mejoramos la performance vs usar expresiones regulares literales. (Solo coloque algunos TAGS, pero basta con agregar más a la lista).
Y a continuación el método que pasado el contenido en HTML retorna un arreglo de objetos; donde en la primera posición va el contenido en texto plano (sin los TAGS HTML) y en la segunda posición la cantidad de caracteres que pertenecen a los TAGS.
...
/**
* @param content
* @return [String, Integer]
*/
private Object[] removeAndCountHtmlTags(String content) {
String result = content;
int htmlCharCount = 0;
for (int i = 0; i < HTML_TAG_REXP.length; i++) {
// create the matcher against the result
Matcher m = HTML_TAG_REXP[i].matcher(result);
// while send a message to find a match group is true
while (m.find()) {
LOG.info("matcher group - " + m.group(0));
// count the number of chars that match
// the group
htmlCharCount += m.group(0).length();
// replace first ocurrence (eliminate tags)
result = m.replaceFirst("");
// and send the message again to find the next
m = HTML_TAG_REXP[i].matcher(result);
}
}
return new Object[] {result, new Integer(htmlCharCount)};
}
...


7 Comentarios
November 12th, 2009 at 3:36 pm
Justamente postee algo de Regex Expressions en uno de mis BLOGs:
http://viviendoconjavaynomoririntentandolo.blogspot.com/search/label/Regex%20Expressions
March 22nd, 2010 at 1:23 pm
Hola Jorge, bueno ha pasado harto tiempo desde que se publicó este post, pero quiero dar a conocer una solución más simple para el mismo problema:
private Object[] removeAndCountHtmlTags(String content) {
String texto = content.replaceAll(“\\”,”");
return new Object[] {texto, new Integer(content.length() – texto.length())};
}
Primero, se obtienen el texto sin tags HTML.
Segundo, se resta la cantidad de caracteres del contenido (HTML + texto) con el texto sin tags HTML.
March 22nd, 2010 at 1:26 pm
En el comentario anterior el editor me ‘comió’ los signos < u > por lo que la expresión regular sería:
String texto = content.replaceAll(“\\<.*?>”,”");
March 22nd, 2010 at 7:40 pm
Sorry por revivir temas anteriores…
En el comentario anterior el editor me ‘comió’ los signos < u >
por lo que la expresión regular sería:
String texto = content.replaceAll(“\\<.*?>”,”");
Saludos.-
March 22nd, 2010 at 8:10 pm
Hola Eugenio,
Gracias por escribir, pero tu solución lo que resuelve es eliminar los caracteres “<>“, no resuelve el problema, que es escapar el HTML y por otro lado retornar de todo el texto la cantidad de caracteres que son HTML. Fijate en el ejemplo, donde se retorna “Presione Aquí” (Texto que no es HTML) y 40 carácteres (cantidad de caracteres que representan HTML).
Saludos.
March 22nd, 2010 at 10:14 pm
Jorge, debo decir que mi solución efectivamente elimina los los tags < y > y también todo lo que esté dentro de ellos. Por ejemplo: si tengo el tag html A, <a href=”link”>Hola</a> el resultado será: Hola.
Luego la cantidad de caracteres HTML es la diferencia del texto completo menos los caracteres que no son HTML.
De hecho tuve que hacer esto en mi tesis, por eso te puedo decir con toda seguridad que funciona.
“\\<.*?>”
March 22nd, 2010 at 10:50 pm
Yeah, tienes razón, gracias Eugenio, excelente solución y disculpas por dudar de tu solución a simple vista.
Deja tu Comentario