Cómo hacer un substring de una cadena HTML

Escrito por el .
blog-stack java planeta-codigo planeta-linux programacion
Comentarios

Java

Una de las cosas que he tenido que resolver en Blog Stack es como conseguir un extracto del contenido completo de una cadena que es HTML. Esto lo he usado en los diferentes feeds de Blog Stack donde solo se muestra el extracto de cada artículo y no el texto completo. A primera vista puede parecer fácil pero no lo es tanto, cortar una cadena que es html haciendo un substring puede ocasionar problemas si se hace en un mal punto de la cadena y luego esa cadena cortada se inserta como contenido de nuevo el una página web. Lo más probable que ocurra es una desmaquetación de la página o que los estilos aparezcan mal pero puede dejar estropeada la página completa.

Por ejemplo, si tenemos la siguiente cadena y la cortamos en un mal punto y luego insertamos en una página html ese contenido lo que ocurrirá es que todo el texto a continuación de él aparecerá en negrita.

1
2
3
<strong>Lorem ipsum ad his scripta blandit partiendo, 
eum fastidii accumsan euripidis in, 
eum liber hendrerit an.</strong>
1
<strong>Lorem ipsum ad his scripta blandit partiendo, eum fastidii

Usar una expresión regular tampoco es solución, con alguna puede parecer que en algún caso funciona pero posiblemente para cada expresión regular podamos encontrar un html para el que no sirva. La expresión regular puede ser complicada.

Para dar solución a este problema podemos emplear jsoup. Jsoup es una librería Java que nos permite manipular el html, desde extraer en forma de texto plano el contenido hasta modificar el html empleando una API. Empleando esta librería podemos ir extrayendo el contenido para contar cuantos caracteres de texto contiene el html y a la vez crear un extracto del documento html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public String getContentExcerpt() {
    // Obtener el documento que representa al contenido del que extraer el extracto
 Document document = Jsoup.parse(getContent());
    final StringBuffer excerpt = new StringBuffer();
    final List<Node> nodes = new ArrayList<>();
    // Recorrer los nodos del documento
 document.traverse(new NodeVisitor() {
        @Override
        public void tail(Node node, int depth) {
        }

        @Override
        public void head(Node node, int depth) {
            if (excerpt.length() > Globals.POST_EXCERPT_LENGHT) {
                // Se ha llegado al límite de caracteres del extracto, recoger los nodos posteriores
             nodes.add(node);
            }
            if (node instanceof TextNode) {
                // Añadir los caracteres al extracto, para contar el número de caracteres recorridos
             TextNode textNode = (TextNode) node;
                excerpt.append(textNode.text());
            }
        }
    });
    // Eliminar los nodos posteriores del extracto
 for (Node node : nodes) {
        node.remove();
    }
    // Obtener el extracto del documento
 return document.body().html();
}

Empleando esta librería la cadena del ejemplo anterior podría quedar:

1
<strong>Lorem ipsum ad his scripta blandit partiendo, eum fastidii</strong>

El resultado aplicando está solución puede verse en el feed de la portada de Blog Stack donde se muestra una entradilla o extracto del inicio del contenido de cada uno de los artículos.

El código fuente de Blog Stack está disponible en un repositorio de GitHub donde puede verse el código completo.