# Parsing bricht ab



## oschli (10. Mrz 2006)

Hi,

nachdem ich in einem anderen Thread nach einer Konkatenation von XML Files gefragt habe(Siehe Link). Wurde mir gerate die XML-Files mit SAX zu parsen.

www.java-forum.org/de/viewtopic.php?t=28730

Dies habe ich durch den unten stehenden Code realisiert.  Allerdings bricht das Parsen bei einer bestimmten Größe der XML Files ab. Und zwar an der Stelle wo ich das Datum einlesen will. 

Es wird dann an stelle von 02-01-2006 nur noch 02-01-20 ausgegeben. Da die Funktion public void characters(char ch[], int start, int length) nur noch mit den Parametern start=2040 length=8 aufgeufen wird. Bei den läufen davor jedoch mit length gleich=10.

Woran könnte das liegen?


```
package monitoringclient.logic;

import java.util.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

import monitoringclient.model.MyDisk;
import monitoringclient.model.MyInstance;
import monitoringclient.model.MyPing;




public class MyEventHandler extends DefaultHandler {
	
	

	public MyEventHandler (){

		myInstanceList_=new LinkedList();
	 
	}
	
	public void startElement(String uri, String qname, String name, Attributes atts){
		
		if(name.equalsIgnoreCase("Instance")){
			aMyInstance_= new MyInstance();
		}
		else if(name.equalsIgnoreCase("Hostname")){
			currentElement="Hostname";
		}
		else if(name.equalsIgnoreCase("Port")){
			currentElement="Port";
		}
		else if(name.equalsIgnoreCase("Date")){
			currentElement="Date";
		}
		else if(name.equalsIgnoreCase("Time")){
			currentElement="Time";
		}
		else if(name.equalsIgnoreCase("SMTP")){
			 aPing_ = new MyPing();
		}
                .... noch weitere zuweisungen
		else{
			currentElement="nothing";
		}
	}
	
	public void endElement(String uri, String name, String qname){
		if(qname.equalsIgnoreCase("Instance")){
			//myInstanceList_.add(aMyInstance_);
			//startParsing
			System.out.println("Eventueller start von Parsing");
			this.aMyInstance_=null;
		}
		else if(qname.equalsIgnoreCase("SMTP")){
			aMyInstance_.setSMTP(aPing_);
			aPing_=null;
		}
		else if(qname.equalsIgnoreCase("DB")){
			aMyInstance_.setDB(aPing_);
			aPing_=null;
		}
		else if(qname.equalsIgnoreCase("Disk")){
			aMyInstance_.addDisk(aDisk_);
			aDisk_=null;
			
		}
		
	}
	
	
	
	public void characters(char ch[], int start, int length){
		String value = new String (ch, start, length);
		if(!value.trim().equals("")){
			
			if(currentElement.equalsIgnoreCase("Hostname")){
				aMyInstance_.setHostname(value);
			}
			else if(currentElement.equalsIgnoreCase("Port")){
				aMyInstance_.setPort(value);
			}
			else if(currentElement.equalsIgnoreCase("Date")){
				System.out.println(value);
				aMyInstance_.setDate(value);
			}
			else if(currentElement.equalsIgnoreCase("Time")){
				System.out.println(value);
				aMyInstance_.setTime(value);
			}
			...
			noch adds			
		}
	}

	
	public LinkedList getInstance(){
		return this.myInstanceList_;
	}
	
	
	private LinkedList myInstanceList_;
	private String currentElement;
	private MyInstance aMyInstance_;
	private MyPing aPing_;
	private MyDisk aDisk_;

}
```


----------



## Roar (10. Mrz 2006)

es ist nicht garantiert, dass characters() für jeden Text abschnitt genau einmal aufgerufen wird. du musst damit rechnen, dass characters() mehrmals hintereinander aufgerufen wird und den string teilweise liefert. mach mal ein println() an den anfang der characters() methode und die gelieferten zeichen aus.


----------



## oschli (10. Mrz 2006)

Das gibt er beim Fehler aus.



```
<Instance ID="1"><Hostname>liyy001</Hostname><Port>7001</Port><Date>02-01-2006</Date><Time>09:00:01</Time>
<Instance ID="1"><Hostname>liyy001</Hostname><Port>7001</Port><Date>02-01-20
monitoringclient.date.MyDate$WrongDate
	at monitoringclient.date.MyDate.<init>(MyDate.java:61)
	at monitoringclient.model.MyInstance.setDate(MyInstance.java:31)
	at monitoringclient.logic.MyEventHandler.characters(MyEventHandler.java:127)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.characters(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanContent(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
	at javax.xml.parsers.SAXParser.parse(Unknown Source)
	at javax.xml.parsers.SAXParser.parse(Unknown Source)
	at monitoringclient.TestApplication.main(TestApplication.java:95)
06</Date><Time>09:30:01</Time>
```

Warum funktioniert es dann bis dahin? Reines Glück ?


----------



## Roar (10. Mrz 2006)

"06</Date><Time>09:30:01</Time> "
:autsch:
wie geht das denn, is dein xml kaputt? zeig mal die entsprechenden tags (oder is das in einer cdata section?)

> Warum funktioniert es dann bis dahin? Reines Glück ?
ja, anscheinend 
du musst halt das, was characters() übergibt zwischenspeichern und deine nstring daraus zzusammensetzen.

edit: ich frag mich noch immer, warum da die tags übergeben werden? :?


----------



## oschli (10. Mrz 2006)

Genau nach 40 solcher Instanzen bricht er ab.

```
<Instance ID="1">
	<Hostname>liyy001</Hostname>
	<Port>7001</Port>
	<Date>01-01-2006</Date>
	<Time>07:00:02</Time>
	<SMTP>
		<Hostname>LIPC175</Hostname>
		<Reply>Failed</Reply>
		<Replytime>100</Replytime>
	</SMTP>
	<DB>
		<Hostname>LIPC175</Hostname>
		<Reply>Failed</Reply>
		<Replytime>100</Replytime>
	</DB>
	<OS>
		<CPULoad>0.67</CPULoad>
		<Filesystem>
			<Disk>
				<Name>/dev/hda2</Name>
				<UsedSpace>7</UsedSpace>
			</Disk>
		</Filesystem>
		<Swap>
			<SwapUsed>0</SwapUsed>
			<SwapTotal>1032152</SwapTotal>
		</Swap>
	</OS>
	<***>
		<Applikation>
			<State>UP</State>
		</Applikation>
		<License>
			<SI>
				<Floating>
					<Number>0</Number>
					<User/>
				</Floating>
			</SI>
			
		</License>
		<Trigger>
			<TriggerInformation>
				<Client>IM</Client>
				<Name>checkAccount</Name>
				<Success>0</Success>
				<Total>0</Total>
			</TriggerInformation>
			
		<***Cache>
			<Percent>0.25</Percent>
			<UsedBytes>1048576</UsedBytes>
		</***Cache>
	</***>
</Instance>
```


----------



## Roar (10. Mrz 2006)

tjo, wie gesagt: speicher die werte die characters() kriegt zwischen, und bastel dir daraus wenn alles da ist nen string.


----------



## oschli (10. Mrz 2006)

kannst du mir eventuell ne anregung geben da ich nicht weiß wie ich da anfangen soll?


----------



## Roar (10. Mrz 2006)

hm auf die schnelle fällt mir ein:
instanzvariable StringBuilder characterBuffer;
in der characters() methode steht *nur*: characterBuffer.append(new String(...));
das if(currentElement...) ... currentElement.setXXX(characterBuffer.toString()); steht dann in der methode endElement(). am ende der endElement() nicht vergessen den buffer zu löschen: characterBuffer.setLength(0);


----------



## oschli (10. Mrz 2006)

Da bekomm ich immer ne NullPointerException bei append.

```
public void characters(char ch[], int start, int length){
		String value=new String(ch, start, length);
		if(!value.trim().equals("")){
			System.out.println(value);
			characterBuffer.append(value);
		}
	}
```


----------



## Roar (10. Mrz 2006)

du hast characterBuffer auch instantiiert, ja?


----------



## oschli (10. Mrz 2006)

Oooops  :wink: 

Danke

Läuft zwar noch nicht durch aber dass werd ich schon noch hinbekommen.


----------



## Bleiglanz (12. Mrz 2006)

ich würde die abfrage auf "" weglassen

roar mein folgendes


character Event:
============

wenn vorheriger Event KEIN character event, dann neuen StringBuilder machen und char[]s ansammeln

wenn vorheriger Event ein character event war, dann weiter ansammeln in einem StringBuilder; 

beliebiger Event:
============

wenn vorheriger Event ein character Event, dann diese char -Sammlung "abschliessen", d.h. den ganzen String aus dem StringBuilder holen und verarbeiten


is leider etwas kompliziert, geht aber nicht anders - weil du sonst nicht erkennen kannst, wann dein String fertiggebaut ist

liegt am Puffern des SAX-Parsers, soll ja effizient sein


----------

