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
ositiveInteger" use="required"/>
</xsd:complexType>
<!-- Relationship player-matchPlayer -->
<xsd:complexType name="matchPlayerType">
<xsd:attribute name="playerID" type="xsd
ositiveInteger" 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:
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
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
</xsd:complexType>
<!-- Relationship player-matchPlayer -->
<xsd:complexType name="matchPlayerType">
<xsd:attribute name="playerID" type="xsd
</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