El analizador JAVA SAX divide llamadas a caracteres ()

Estoy haciendo un proyecto para analizar algunos datos del XML.

Por ejemplo, el XML es

abcdefghijklmno 

Necesito analizar “abcdefghijkmnlp”.

Pero mientras pruebo mi análisis, descubro un gran problema:

 public class parser{ private boolean hasABC = false; //Constructor HERE ...................... ...................... @Override public void startDocument () throws SAXException{ } @Override public void endDocument () throws SAXException{ } @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException{ if ("abc".equalsIgnoreCase(localName)) { this.hasABC = true; } } @Override public void endElement(String namespaceURI, String localName, String qName) throws SAXException{ if ("abc".equalsIgnoreCase(localName)) { this.hasABC = false; } } @Override public void characters(char ch[], int start, int length){ String content = new String(ch, start, length).trim(); if(this.hasABC){ System.out.println("ABC = " + content); } } } 

Descubro que el analizador ha analizado la etiqueta dos veces. La impresión del sistema es

ABC = abcdefghi

ABC = jklmno << ============ dividir el mensaje

¿Por qué el analizador automático devuelve la llamada a los caracteres () dos veces ????

¿El XML tiene algo de “\ n” o “\ r” ???

El analizador llama al método de characters más de una vez, porque puede y permite por especificación. Esto ayuda al analizador rápido y mantiene su huella de memoria baja. Si desea una única cadena, cree un nuevo objeto StringBuilder en startElement y endElement método endElement .

Se sorprenderá, pero este es un comportamiento documentado, es decir, no puede suponer que el analizador leerá y devolverá todos los datos de texto de un elemento en una única callback. Tuve la misma experiencia antes. Necesita codificar para manejar esta situación o puede cambiar al analizador Stax . Puede usar CharArrayWriter para acumular datos a través de múltiples devoluciones de llamada.

Consulte a continuación el JavaDoc de ContentHandler.characters (…)

El analizador llamará a este método para informar cada fragmento de datos de caracteres. Los analizadores SAX pueden devolver todos los datos de caracteres contiguos en un solo fragmento, o pueden dividirlo en varios fragmentos; sin embargo, todos los personajes en un solo evento deben provenir de la misma entidad externa para que el Localizador brinde información útil.

Puede cambiar el método de inicio, fin y carácter como:

  • agregar una variable de contenido “global”
  • luego null it in start method (content == null)
  • en el método final puede imprimir o agregar esa cadena de contenido a algún objeto
  • en el método de caracteres puedes hacer if / else:

     if (content == null) { content = new String(ch, start, length); } else { content += new String(ch, start, length); } 

    Manera brutal (mejor hacerlo con stringbuilder) pero funciona y “string” ya no está dividido.

Esta es una característica de SAX. El analizador puede dividir los segmentos de texto y llamar al método de los characters tantas veces como quiera.

La razón de esto es el rendimiento, que SAX prioriza sobre la facilidad de uso. SAX puede haber agotado su memoria intermedia interna, por lo que para evitar la copia, pasa los datos que tiene hasta el momento a su código.