2010-12-31 7 views
19

Estoy haciendo un proyecto para analizar algunos datos del XML.JAVA SAX parser llamadas divididas a caracteres()

Por ejemplo, el XML es

<abc>abcdefghijklmno</abc> 

necesito para analizar "abcdefghijkmnlp".

Pero mientras pongo a prueba mi análisis sintáctico, 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 de impresión Sistema de salir es decir,

ABC = abcdefghi

ABC = JKLMNO < < ============ divide el mensaje

Por qué el analizador automático volver a llamar a los personajes() dos veces ????

¿El XML tiene algo de "\ n" o "\ r" ???

+0

Hola @Rebecca, encontraste la solución para este problema, estoy enfrentando el mismo problema. – Ramesh

Respuesta

32

El analizador llama al método 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 sola cadena, cree un nuevo objeto StringBuilder en el startElement y trátelo en el método endElement.

+0

Sí, estoy usando una variable gobal para almacenar el texto en charaters() e imprimir esta variable en endElement(). – rebecca

+0

@rebecca el fragmento de código de la pregunta no hace eso, supongo que se refiere a un nuevo código fijo ahora? :) – rogerdpack

7

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 devolución de llamada. Tuve la misma experiencia antes. Necesita codificar para manejar esta situación o puede cambiar al Stax parser. Puede usar CharArrayWriter para acumular los datos en múltiples devoluciones de llamada.

Véase más adelante de la JavaDoc of ContentHandler.characters(...)

El Analizador llamará a este método para informe de cada trozo de datos de caracteres. Los analizadores SAX pueden devolver todos los datos contiguos de caracteres en un solo fragmento, o ellos pueden dividir en varios fragmentos; sin embargo, todos los caracteres en cualquier evento individual deben provenir de la misma entidad externa para que el Localizador proporcione información útil.

+0

Realmente me gustaría que hubiera alguna bandera para * no * hacer esto: | – rogerdpack

3

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

La razón de esto es el rendimiento, que SAX prioriza por su 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.

4

Puede cambiar comienzo, el final y el método personaje como:

  • añadir una variable "global" contenido
  • un valor nulo en el método start (contenido == null)
  • en fin del método u puede println o añadir contenido a esa cadena de algún objeto
  • en el método de caracteres u puede hacer if/else:

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

    Brutal way (mejor hacerlo con stringbuilder) pero funciona y "string" ya no está dividido.