2010-12-31 6 views
19

Ich mache ein Projekt, um einige Daten aus dem XML zu analysieren.JAVA SAX-Parser Anrufe auf Zeichen aufteilen()

Zum Beispiel kann die XML ist

<abc>abcdefghijklmno</abc> 

ich brauche "abcdefghijkmnlp" zu analysieren.

Aber während ich meine Parse testen entdecke ich ein großes Problem:

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); 
      } 
     } 
    } 

ich feststellen, dass der Parser den Tag zwei Mal System-Druck aus ist,

ABC = abcdefghi

analysiert hat

ABC = jklmno < < ============ spaltete die Nachricht

Warum der Parser Auto die Zeichen() zweimal zurückrufen ???

Ist die XML einige "\ n" oder "\ r" ???

+0

Hallo @Rebecca, hast du eine Lösung für dieses Problem gefunden, ich bin mit dem gleichen Problem konfrontiert. – Ramesh

Antwort

32

Parser ruft characters Methode mehr als einmal, weil es pro Spezifikation erlaubt und erlaubt. Dies hilft beim schnellen Parser und hält den Speicherbedarf gering. Wenn Sie eine einzelne Zeichenfolge möchten, erstellen Sie ein neues StringBuilder Objekt in der startElement und verarbeiten Sie es auf endElement Methode.

+0

Ja, ich verwende eine globale Variable, um den Text in charaters() zu speichern und diese Variable bei endElement() auszugeben. – rebecca

+0

@rebecca das Code-Snippet aus der Frage nicht das, ich nehme an, Sie beziehen sich auf einige neu festgelegten Code jetzt? :) – rogerdpack

7

Sie werden überrascht sein, aber dies ist ein dokumentiertes Verhalten, d. H. Sie können nicht davon ausgehen, dass der Parser alle Textdaten eines Elements in einem einzelnen Callback lesen und zurückgeben wird. Ich hatte früher die gleiche Erfahrung. Sie müssen einen Code erstellen, um mit dieser Situation umzugehen, oder Sie können zu Stax parser wechseln. Sie können CharArrayWriter verwenden, um die Daten über mehrere Rückrufe hinweg zu sammeln.

Siehe unten vom JavaDoc of ContentHandler.characters(...)

Der Parser dieser Methode Bericht nennt jeden Chunk von Zeichendaten. SAX-Parser können alle zusammenhängenden Zeichendaten in einem einzelnen Chunk zurückgeben, oder sie können in mehrere Chunks teilen; jedoch müssen alle Zeichen in einem beliebigen Einzelereignis von der gleichen externen Einheit stammen, damit der Locator nützliche Informationen bereitstellt.

+0

Ich wünschte wirklich, es gäbe eine Flagge zu * nicht * tue dies: | – rogerdpack

3

Dies ist eine Funktion von SAX. Der Parser kann die Textsegmente aufteilen und Ihre characters Methode beliebig oft aufrufen.

Der Grund dafür ist die Leistung, die SAX der Benutzerfreundlichkeit vorzieht. SAX hat möglicherweise seinen internen Puffer aufgebraucht, um zu vermeiden, dass es kopiert wird, übergibt es die Daten, die es bis jetzt durch hat, an Ihren Code.

4

Sie können Anfangs-, End- und Zeichenmethode ändern wie:

  • ein "globalen" content Variable hinzufügen
  • dann Methode in Start null (Inhalt == null)
  • in End-Methode u println oder hinzufügen können, dass der Inhalt Zeichenfolge auf ein Objekt
  • in Zeichenmethode kann u machen if/else:

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

    Brutaler Weg (besser mit Stringbuilder) funktioniert aber und "String" ist nicht mehr gespalten.

Verwandte Themen