DefaultHandler characters() wird doppelt aufgerufen

  • Hallo zusammen,


    ich habe einen Datenhandler, der von DefaultHandler erbt, mit dem ich XML Daten parse.
    Die Methode "characters(char ch[], int start, int length)" wird manchmal (ich habe absolut keine Ahnung wieso) doppelt aufgerufen, sodass ein Element in zwei geteilt wird und mein Programm kaputtmacht ;)
    Kann mir da jemand weiterhelfen?


    Viele Grüße
    R2

  • Das ist Standardverhalten von XML-Parsern, im Extremfall kann ein characters-Element ja auch mal einige Megabyte enthalten, darum wird öfters zwischendurch neu angesetzt.


    Du musst immer damit rechnen, dass characters() kleine Abschnitte bastelt (z.B. bei Sonderzeichen).


    Einfach deinen StringBuffer oder ähnliches weiter auffüllen und bei einem Tag-Ende übernehmen und leeren.

  • Das geht auf jeden Fall besser mit einem StringBuffer.


    Die wichtigen Methoden sind myStringBuffer.append(chars), myStringBuffer.toString() und myStringBuffer = new StringBuffer() (dann ist er wieder leer).


    Achja - characters() wird auch für RETURN, LEERZEICHEN, TAB und sonstiges, was zwischen den Tags ist, aber keine Bedeutung hat, aufgerufen.
    Du musst also gucken, ob dein Ergebnis nach toString() überhaupt brauchbare Zeichen enthält.
    Dem Parser ist das egal - könnte ja sein, dass du das gebrauchst, darum liefert er dir alles...

  • Die Methode sieht ja so aus:


    Java
    public void characters(char ch[], int start, int length)


    Wie kriege ich daraus einen StringBuffer?
    Das hier erscheint mir sehr umständlich


    Java
    StringBuffer SB = new StringBuffer(new String(ch,start,length));
  • nein - andersrum... ;)


    Den StringBuffer nimmst du, um die ch[] aufzusammeln - du musst ihn also außerhalb deklarieren.


    Hier mal ein Ausschnitt aus meinem Handler:

  • Bei mir sieht das etwas anders aus...


    Java
    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
    	if (localName.equals("cid")) {
    		_inCid = true;
    	} else if (localName.equals("name")) {
    		_inName = true;
    	} .....
    }


    Damit speichere ich, in welchem Element sich der Parser befindet, um es hier im Folgenden zu unterscheiden.


  • Ich hab dir ja auch nur die Teile gezeigt, die sich mit dem StringBuffer beschäftigen - die ganze restliche Logik hab ich aus Platzgründen weggelassen. ;)


    Aber vom Ablauf sollte folgendes passieren:


    Den StringBuffer neu anlegen in startElement().


    Dann füllen lassen im characters() - können ja mehrere Teile kommen. Aber keine weitere Auswertung in characters().


    Diese Auswertung machst du in endElement() - denn erst dann sind die Zeichen komplett da.


    Wenn dein Dokument aber zwischen Tags manchmal noch Text enthält, musst du auch in startElement() gucken, ob der StringBuffer schon wieder was hat und auswerten.


    Viele Beispiele im Internet mache die Auswertung in characters - bei englischen Texten geht das auch meistens gut, weil keine Umlaute vorkommen. Aber der korrekte Weg ist, im characters() nur zu sammeln was wichtig ist und im endElement() (evtl. auch im startElement()) dann den gelesenen Inhalt verwursten.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!