SAX-Parsing Probleme

MArCus88

Mitglied
Hallo zusammen,

wieder einmal bin ich auf eure geschätzte Hilfe angewiesen. Heute habe ich Probleme bei meiner Softwarehausaufgabe in Java, in der wir einen XML-Parser schreiben sollen. Soweit so gut, ich hab das XML Schema, sowie eine XML welche diese Kriterien erfüllt, erstellt. Nun ist der XML-Parser dran. Entschieden hab ich mich für den SAXParser, über den ich hier: XML and Java - Parsing XML using Java Tutorial ein Tutorial gelesen und versucht habe mich daran zu orientieren. Ich meine auch, dass ich soweit auf dem richtigen Weg bin, allerdings hab ich Probleme beim Ausführen.

Hier mal meine XML:

[XML]<?xml version="1.0" encoding="UTF-8"?>
<spieleListe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Users/marcusc/Documents/Eclipse Projekte/Kickernaut/bin/dialogs/xml/MatchAndPlayerImportSchema.xsd">
<playerList>
<player ID="1">
<firstName>Dieter</firstName>
<familyName>Müller</familyName>
<dateOfBirth>1988-05-14</dateOfBirth>
</player>
<player ID="2">
<firstName>Franz</firstName>
<familyName>Weiss</familyName>
<dateOfBirth>1990-05-04</dateOfBirth>
</player>
<player ID="3">
<firstName>Bernd</firstName>
<familyName>Möller</familyName>
<dateOfBirth>1963-05-06</dateOfBirth>
</player>
<player ID="4">
<firstName>Ruth</firstName>
<familyName>Schmidt</familyName>
<dateOfBirth>1966-12-07</dateOfBirth>
</player>
<player ID="5">
<firstName>Eva</firstName>
<familyName>Kessler</familyName>
<dateOfBirth>1977-12-12</dateOfBirth>
</player>
</playerList>
<matchList>
<match>
<matchDate>2010-12-28</matchDate>
<team>
<teamPlayer playerID="1"/>
<teamPlayer playerID="2"/>
<goals>2</goals>
</team>
<team>
<teamPlayer playerID="3"/>
<teamPlayer playerID="4"/>
<goals>2</goals>
</team>
</match>
</matchList>
</spieleListe>[/XML]

Ich denke mal die Tags sind soweit relativ selbstsprechend. Bei der Applikation geht es um eine einfache Anwendung, mit der sich Kicker-Spiele speichern lassen. Dabei müssen je Match 2 Teams existieren und ein Matchdatum bestehen. Ein Team wiederum kann aus 1 oder 2 Spielern bestehen. Auf diese Spieler wird mittels key/keyref Bezug genommen.

Hier mal das zugehörige XML-Schema(falls es von Belang sein sollte^^):

[XML]<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<!-- Import-Schema für Kickernaut -->
<xsd:element name="spieleListe">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="playerList" maxOccurs="1" type="playerListType"/>
<xsd:element name="matchList" maxOccurs="1" type="matchListType"/>
</xsd:sequence>
</xsd:complexType>

<!-- key/keyref -->
<xsd:key name="playerKey">
<xsd:selector xpath="playerList/player"/>
<xsd:field xpath="@ID"/>
</xsd:key>
<xsd:keyref name="playerFremdKey" refer="playerKey">
<xsd:selector xpath="matchList/match/team/teamPlayer"/>
<xsd:field xpath="@playerID"/>
</xsd:keyref>

<!-- Eindeutigkeit der Player -->
<xsd:unique name="firstName-familyName-dateOfBirth">
<xsd:selector xpath="playerList/player"/>
<xsd:field xpath="firstName"/>
<xsd:field xpath="familyName"/>
<xsd:field xpath="dateOfBirth"/>
</xsd:unique>
</xsd:element>

<!-- matchListType Deklaration -->
<xsd:complexType name="matchListType">
<xsd:sequence>
<xsd:element name="match" type="matchType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>

<!-- playerListType Deklaration -->
<xsd:complexType name="playerListType">
<xsd:sequence>
<xsd:element name="player" type="playerType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>

<!-- Match Deklaration -->
<xsd:complexType name="matchType">
<xsd:sequence>
<xsd:element name="matchDate" type="xsd:date"/>
<xsd:element name="team" type="teamType" minOccurs="2" maxOccurs="2"/>
</xsd:sequence>
</xsd:complexType>

<!-- teamType Deklaration -->
<xsd:complexType name="teamType">
<xsd:sequence>
<xsd:element name="teamPlayer" type="matchPlayerType" minOccurs="1" maxOccurs="2"/>
<xsd:element name="goals" type="xsd:short"/>
</xsd:sequence>
</xsd:complexType>

<!-- playerType Deklaration -->
<xsd:complexType name="playerType">
<xsd:sequence>
<xsd:element name="firstName" type="xsd:string"/>
<xsd:element name="familyName" type="xsd:string"/>
<xsd:element name="dateOfBirth" type="xsd:date"/>
</xsd:sequence>
<xsd:attribute name="ID" type="xsd:positiveInteger" use="required"/>
</xsd:complexType>

<!-- Relationship player-matchPlayer -->
<xsd:complexType name="matchPlayerType">
<xsd:attribute name="playerID" type="xsd:positiveInteger" use="required"/>
</xsd:complexType>
</xsd:schema>[/XML]

Nun möchte ich die XML auslesen und die Inhalte in meine dafür geschriebenen Klassen speichern. Hier mein Code für das Parsing:

Java:
package dialogs.xml;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.jar.Attributes;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

// die Klasse verarbeitet einen XML-Import und reicht die gewonnenen
// Daten an die Applikation weiter
public class XmlParser extends DefaultHandler {

	XMLPlayer actualPlayer;									// der Spieler der aktuell eingelesen wird
	XMLMatch actualMatch;									// das Match das aktuell eingelesen wird
	XMLTeam actualTeam;										// das Team welches aktuell eingelesen wird
	
	ArrayList<XMLPlayer> players;						 	// Liste der bisher eingelesenen Spieler
	ArrayList<XMLMatch> matches;						 	// Liste der bisher eingelesenen Matches
	String tempVal;							// speichert den aktuellen Simple-Content
	
	// Konstruktor
	public  XmlParser() {
		this.parseDocument();
	}
	
	// wird unmittelbar vom Konstruktor aufgerufen und startet das "XML-Parsing"
	public void parseDocument() {
		
		// instantiiert eine neue SAXParserFactory
		SAXParserFactory spf = SAXParserFactory.newInstance();
		try {

			// instantiiert einen neuen SAXParser
			SAXParser sp = spf.newSAXParser();

			File xmlFile = new File("bin/dialogs/xml/SpieleListe.xml");
			
			// sagt dem Parser welche XML er verarbeiten soll und registriert
			// diese Klasse als Default-Event-Handler für Callback-Events
			sp.parse(xmlFile, this);
			
			System.out.println("XML-Arbeit getan!");

		}catch(SAXException se) {
			se.printStackTrace();
		}catch(ParserConfigurationException pce) {
			pce.printStackTrace();
		}catch (IOException ie) {
			ie.printStackTrace();
		}
	}
	
	// wird aufgerufen wenn ein Start-Tag gefunden wurde
	public void startElement(String uri, 
							 String localName, 
							 String qName, 
							 Attributes attributes) throws SAXException {
		
		// den temporären String zurücksetzen
		tempVal = "";
		
		// prüfen, ob der Start-Tag eines player-Elements gefunden wurde
		if(qName.equalsIgnoreCase("player")) {
			
			// eine neue Playerinstanz erstellen
			actualPlayer = new XMLPlayer();
			
			// dem Player die mitgelieferte "ID"-Attribut übergeben
			actualPlayer.setPlayerID(Integer.parseInt(attributes.getValue("ID")));
			
		} else if(qName.equalsIgnoreCase("match")) {
			
			// ein neues Match erstellen
			actualMatch = new XMLMatch();
			
		} else if(qName.equalsIgnoreCase("team")) {
		
			// ein neues Team erstellen
			actualTeam = new XMLTeam();
		
		} else if(qName.equalsIgnoreCase("teamPlayer")) {
			
			// den gefundenen Spieler dem aktuellen Team zuführen
			actualTeam.addPlayer(Integer.parseInt(attributes.getValue("playerID")));
		} else if(qName.equalsIgnoreCase("playerList")) {
			
			// neue Spielerliste erstellen
			players = new ArrayList<XMLPlayer>();
		
		} else if(qName.equalsIgnoreCase("matchList")) {
			
			// neue Matchliste erstellen
			matches = new ArrayList<XMLMatch>();
		}
	}

	// wird aufgerufen wenn Simple-Content eingelesen wird
	public void characters(char[] ch, 
					       int start, 
					       int length) throws SAXException {
		
		tempVal = new String(ch,start,length);
	}
	
	// wird aufgerufen wenn Leerraum gefunden wurde
	public void ignorableWhitespace(char[] ch, int start, int length)
    {
    }

	// wird aufgerufen wenn ein End-Tag gefunden wurde
	public void endElement(String uri, 
						   String localName,
						   String qName) throws SAXException {
		
		// wurde ein "player"-Endtag gefunden?
		if(qName.equalsIgnoreCase("player")) {
			
			// fügt den Player in die Spielerliste hinzu
			players.add(actualPlayer);
			actualPlayer = null;
			
		} else if(qName.equalsIgnoreCase("firstName")) {
			
			// übergibt dem Spieler den Vornamen
			actualPlayer.setFirstName(tempVal);
			
		} else if(qName.equalsIgnoreCase("familyName")) {
			
			// übergibt dem Spieler den Familiennamen
			actualPlayer.setFamilyName(tempVal);
			
		} else if(qName.equalsIgnoreCase("dateOfBirth")) {
			
			// übergibt dem Spieler sein Geburtsdatum
			actualPlayer.setDateOfBirth(tempVal);
		}
		
		// wurde ein "match"-Endtag gefunden?
		if(qName.equalsIgnoreCase("match")) {
			matches.add(actualMatch);
			actualMatch = null;
		} else if(qName.equalsIgnoreCase("match")) {
			actualMatch.setMatchDate(tempVal);
		}
		
		// wurde ein "team"-Endtag gefunden?
		if(qName.equalsIgnoreCase("team")) {
			actualMatch.addTeam(actualTeam);
			actualTeam = null;
		}
	}
}

Beim Ausführen bekomme ich eine NullPointerException um die Ohren geworfen, drum hab ich durchs Setzen von Breakpoints versucht dem Fehler auf den Grund zu gehen. Es stellte sich heraus, dass die Methode characters(char,int,int) als erste aufgerufen wird, nur frage ich mich warum. Das erste Event was auftreten müsste, ist doch startElement(String,String,String,Attributes) oder nicht? Weil zuerst müsste ja ein Starttag gefunden werden, woraufhin Speicher für die jeweilige Klasse reserviert wird.

Danke für jegliche Hilfe vorab und noch einen schönen Abend!

Gruß
Marcus
 

Noctarius

Top Contributor
Das erste Eventu das auftreten sollte ist ein startDocument. Welchen SAX Driver nutzt du? Hat dein Dokument eventuell einen UTF-8 BOM am Anfang und der SAX Driver unterstützt das nicht, dass er als erstes characters aufruft?
 

MArCus88

Mitglied
@Noctarius:
Okay das ist mit startDocument ist richtig, da hab ich mich missverständlich ausgedrückt. In meinem Code sollte die erste Methode die startElement-Methode sein. Es ist ja nicht erforderlich die Methode startDocument zu implementieren oder?

Welchen SAX-Driver ... oh jee das kann ich garnicht sagen. In der XML-Materie bin ich noch Neuling, kann aber sagen, dass ich beides (Schema und die Beispiel-XML) im Editor der Eclipse Enterprise Edition geschrieben habe.
 

Noctarius

Top Contributor
Lass dir vom Locator mal die Position ausgeben, an welcher der Fehler auftritt. Klingt spontan nach einem unsichtbaren Zeichen vor dem XML.
 

MArCus88

Mitglied
Okay, kannst du mir sagen wie ich das bewerkstellige? Tut mir leid für die Anfängerfrage, aber mit Eclipse bin ich noch nicht so bewandert^^
 

Noctarius

Top Contributor
Exceptions fangen und in der SAXException kannst du dir Zeile und Spalte holen. Dies kannst du entweder erreichen, in dem du um parser.parse einen try/catch legst oder durch überschreiben der fatalError Methode (oder so ähnlich).

Hab auch noch nicht soviel mit SAX gemacht, versuche aber gerade Lycia um einen Streaming-Parser zu erweitern ;)
 

Noctarius

Top Contributor
Vermutlich aus dem Constructor der String-Class weil das Array null ist? Kannst doch einfach mal schauen was Null ist und einen passenden Null-Check einbauen.
 

MArCus88

Mitglied
Okay alles klar mein aktueller Spieler (actualPlayer) ist null, da das erste Tag, das gefunden wurde, das "firstName"-Tag ist. Demnach überliest er wirklich alle vorhergehenden Tags. Sprich es wird kein Speicherplatz für den aktuellen Spieler reserviert. Nur weiß ich nach wie vor nicht, woran es liegt dass er die vorhergehenden Tags überliest :-(
 

Noctarius

Top Contributor
Die Frage ist doch sollten davor überhaupt Tags gekommen sein? Speicher dir mal den Locator (überschreiben der Methode setDocumentLocator) und lass dir in characters die Position ausgeben.
 

MArCus88

Mitglied
Gut ich hab jetzt meine characters-Methode um die Zeile:

Java:
System.out.println("Column: "+this.documentEventsLocator.getColumnNumber()+" Line: "+this.documentEventsLocator.getLineNumber());

erweitert und kann mir so Line und Column ausgeben lassen. Worauf beziehen sich die Columns in meiner XML?

P.S.: documentEventsLocator ist der in der von dir beschriebenenen überschriebenene Methode gespeicherte Locator.
 

MArCus88

Mitglied
Okay die Zeile kann ich zuordnen^^ Lediglich unter einer Spalte innerhalb einer XML kann ich mir nichts vorstellen. Ich hab doch in einer XML gar keine tabellarische Ansicht oder doch?

Achja beim Debuggen ist mir aufgefallen, dass characters eine Reihe von "/n" und"/t" an meine temporäre Stringvariable übergibt. Kann das schon des Rätsels Lösung sein? Sprich dass ich mit Zeilenumbrüchen und Tabulatoren gearbeitet hab? So wollte ich meine XML nur lesbar halten.
 

Noctarius

Top Contributor
Achja beim Debuggen ist mir aufgefallen, dass characters eine Reihe von "/n" und"/t" an meine temporäre Stringvariable übergibt. Kann das schon des Rätsels Lösung sein? Sprich dass ich mit Zeilenumbrüchen und Tabulatoren gearbeitet hab? So wollte ich meine XML nur lesbar halten.

Lass dir vom Locator mal die Position ausgeben, an welcher der Fehler auftritt. Klingt spontan nach einem unsichtbaren Zeichen vor dem XML.

Schau mal hier: How to Manage White Space
 

MArCus88

Mitglied
Schade ich hab mich daran gehalten was in dem Tutorial stand, leider brachte es nicht den gewünschten Effekt. Ich hab mir die dort beschriebene Filterklasse erstellt und meine characters-Methode an die characters-Methode dort weitergereicht.

Meine Parser characters-Methode schaut nun so aus:

Java:
	// wird aufgerufen wenn Simple-Content eingelesen wird
	public void characters(char[] ch, 
					       int start, 
					       int length) throws SAXException {
		System.out.println("Column: "+this.documentEventsLocator.getColumnNumber()+" Line: "+this.documentEventsLocator.getLineNumber());
		WhitespaceFilter filter = new WhitespaceFilter();
		filter.characters(ch,start,length);
		tempVal = filter.getFilteredString();
	}

Die Klasse, die mir das char-Array filtert so:

Java:
public class WhitespaceFilter extends XMLFilterImpl {
		
	// der gefilterte String
	String filteredString;
		
	// filtert die Whitespaces aus der XML
	public void characters(char[] ch, int start, int length)  throws SAXException { 
	    if (!new String(ch, start, length).trim().equals("")) 
	       super.characters(ch, start, length); 
	    String temp = new String(ch,start,length);
	    filteredString = temp;
	}
	
	// gibt den gefilterten String zurück
	public String getFilteredString() {
		return filteredString;
	}
}

P.S.: Das mit den Spalten hab ich nun verstanden, Eclipse zeigt es mir ja an^^ Eine Spalte bezeichnet ein Zeichen.
 

MArCus88

Mitglied
Ups ja wie dumm von mir. Nach der ganzen Zeit seh' ich den Wald vor lauter Bäumen net mehr. Die Zeile muss natürlich so ausschauen (wenn ich mich net vertan hab):

Java:
 if (!new String(ch, start, length).trim().equals("/n") || !new String(ch, start, length).trim().equals("/t"))

Aber ich denke nicht dass es ein Whitespace-Problem ist. Zwischenzeitlich hatte ich nämlich schon manuell alle Whitespaces entfernt und die NullPointerException kommt trotzdem >.<
 

MArCus88

Mitglied
Ja dann wird es wirklich etwas anderes sein! Oh Mann ich hol mir erstmal 'nen Kaffee, nicht mal den korrekten Backslash bekomm' ich noch hin :-D
 

MArCus88

Mitglied
Sorry für den dreisten Doppelpost, aber ich hab jetzt zu Testzwecken die XML eines Kommilitonen eingesetzt und komme auf denselben Fehler. Wir haben die ziemlich gleiche XML, drum hab ich nur ein wenig Code anpassen müssen. Ich schau mal ob ich alle Tags abgefragt hab, die auftreten können, eventuell liegt ja hier der Fehler!
 

MArCus88

Mitglied
So ich wollte eben nochmal Bescheid geben, dass ich das Problem nun gelöst hab. Den Code hab ich etwas umgeschrieben, so dass ich nun den XmlReader als Parser benutze. Außerdem hab ich herausgefunden, dass ein weiterer Fehler wahrscheinlich in if-Bedingungen steckte, in denen ich die Start-Tags abgefragt hab. Dort habe ich noch nämlich den Parameter "qName" und nicht den "localName" abgefragt. Nun ist das geändert und siehe da, es geht :)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Probleme beim SAX parsing XML & JSON 4
M Gson Enum parsing XML & JSON 0
M XML Parsing von Paketen XML & JSON 12
T XML-Parsing: Whitespace zw. Elementen wird nicht ignoriert XML & JSON 4
O Parsing bricht ab XML & JSON 11
Kirby.exe Probleme mit XML XPATH Select XML & JSON 3
N Probleme bei der Formatierung beim Einfügen und löschen über DOM XML & JSON 7
G Probleme mit Jsoup in .jar File XML & JSON 11
K JAX-WS Bindin-Probleme XML & JSON 1
B Probleme mit RelativeLayout XML & JSON 1
L Jackson JSON: Probleme beim einlesen XML & JSON 1
K XOM Builder Probleme XML & JSON 3
N Jsoup: PHP-Tags bereiten Probleme? XML & JSON 2
M Probleme mit XPath bei Java XML & JSON 5
hdi Probleme beim Erstellen einer XML XML & JSON 7
F Probleme beim html parsen mit tagsoup XML & JSON 4
M Probleme beim Parsen eines gefilterten XML-Dokuments XML & JSON 6
H JAXB Probleme beim Unmarshalling XML & JSON 3
G Probleme mit XML und JTree XML & JSON 9
klattiator Probleme mit Codierung XML & JSON 3
S Probleme beim erstellen einer Jar XML & JSON 12
T XML und Sonderzeichen, Probleme mit ASP.NET Server XML & JSON 2
G Probleme mit Namespaces XML & JSON 5
D Probleme mit Eclipse Modeling Framework (EMF) XML & JSON 2
S PDF Erzeugung - Probleme mit der XML Datei bei Schema-Infos XML & JSON 2
C SAX Probleme beim lesen XML & JSON 4
F JAXB - Nachträglich hinzugefügter Code macht Probleme XML & JSON 2
P Probleme mit JDom . addContent(int index,Collection c) XML & JSON 2
F Unmarshall Probleme XML & JSON 5
byte Probleme beim Parsen von XHTML-Datei XML & JSON 4
R Probleme mit Transformer und StreamResult XML & JSON 4
C Probleme mit Include XML & JSON 10
C POI + jXLS Probleme XML & JSON 3
B DOM DTD laden abschalten, Probleme mit Doctypes und PIs XML & JSON 2
S Probleme mit Jdom XML & JSON 3
G probleme mit package XML & JSON 12
M Probleme mit String XML & JSON 3
H Probleme mit xmlrpc und php XML & JSON 13
B Probleme mit Zugriff auf eXist-Datenbank XML & JSON 9
H Neu bei JAVA- Probleme mit der Integration von Xerces XML & JSON 3
P Probleme mit jdom XML & JSON 5
R JAVA und DOM, probleme beim einfügen von elementen ?????? XML & JSON 6

Ähnliche Java Themen

Neue Themen


Oben