XML mit DTD prüfen

SilverClaw

Aktives Mitglied
Hallo, nun hab ich mal wieder eine Frage, da ich gerade meinen Spiele-Code ein wenig umbauen will, um z.B. Einheitendaten aus einer XML-Datei zu lesen, anstatt sie "hart" im Programm eingebaut zu haben.
Das XML lesen scheint auch wunderbar zu funktionieren. Jetzt dachte ich, ich shcreibe mir kurz mal eine DTD, um sie durchzuprüfen, aber bin jetzt am verzweifeln und finde auch wieder mal keinen, das das selbe Problem zu haben scheint. ;(

Code:
<?xml version="1.0" encoding = "UTF-16"?>
 <!DOCTYPE units SYSTEM "bin/resource/units.dtd">
<units>
	<unit name = "Bauern">
		<health>5</health>
		<cost>10</cost>
		<armor>cloth</armor>
		<speed>infantry</speed>
		<attack name = "Mistgabel" image = "pitchfork" damage = "3.4" range = "Pole">
		</attack>
		<attack name = "Steine" image = "stone" damage = "1.2" range = "short throw">
		</attack>
	</unit>
		<unit name = "Schwertkämpfer">
		<health>7</health>
		<cost>25</cost>
		<armor>chainmail</armor>
		<speed>infantry</speed>
		<attack name = "Schwert" image = "sword" damage = "7.5" range = "close">
			Schwerthieb!
		</attack>
	</unit>
</units>

(Ich weiß, man soll eher Elemente als Attribute benutzen, aber ich fand das irgendwie praktischer. In die tags würden dann Beschreibungstexte zu den Fähigkeiten kommen.)

Code:
<!DOCTYPE units SYSTEM "units.dtd"> 
<!ELEMENT units(unit+)>
<!ELEMENT unit(health, cost, armor, speed, attack*, heal?)>
<!ATTLIST unit name CDATA #REQUIRED)>
<!ELEMENT health (#PCDATA)>
<!ELEMENT cost (#PCDATA)>
<!ELEMENT armor (naked|leather)>
<!ELEMENT speed (immobile|infantry)>
<!ELEMENT attack (#PCDATA)>
<!ATTLIST attack
	name CDATA #REQUIRED
	image CDATA #IMPLIED "none"
	damage CDATA #IMPLED "0.0"
	range (close|pole) #IMPLIED "none"
>

Java:
	public List<Unit> loadUnits() 
			throws SAXException, ParserConfigurationException, IOException {
		
		SAXParserFactory factory = SAXParserFactory.newInstance();
		factory.setValidating(true);
		factory.setNamespaceAware(true);
		XMLReader reader = factory.newSAXParser().getXMLReader();
		reader.setErrorHandler(new ErrorHandler() {
			
			@Override
			public void warning(SAXParseException arg0) throws SAXException {
				System.out.println("ParseWarning: " + arg0.getMessage());
			}
			
			@Override
			public void fatalError(SAXParseException arg0) throws SAXException {
				System.out.println("FATAL ParseError: " + arg0.getMessage());
			}
			
			@Override
			public void error(SAXParseException arg0) throws SAXException {
				System.out.println("ParseError: " + arg0.getMessage());
			}
		});
		reader.parse(new InputSource(ClassLoader.getSystemClassLoader().getResourceAsStream(
				"module/" + module + "/xml/units.xml")));
	return loadedUnits;

Und zuguterletzt bekomme ich die Exception:

FATAL ParseError: Die Markup-Deklarationen, die in der Dokumenttypdeklaration enthalten sind bzw. auf die von der Dokumenttypdeklaration verwiesen wird, müssen ordnungsgemäß formatiert sein.
org.xml.sax.SAXParseException; systemId: file:///C:/Users/username/workspace/NewEraCardGame_v005/bin/resource/units.dtd; lineNumber: 1; columnNumber: 3; Die Markup-Deklarationen, die in der Dokumenttypdeklaration enthalten sind bzw. auf die von der Dokumenttypdeklaration verwiesen wird, müssen ordnungsgemäß formatiert sein.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDecls(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDTDExternalSubset(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(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 com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at resource.RessourceLoader.loadUnits(RessourceLoader.java:54)
at main.Starter.main(Starter.java:26)

Was genau da aber falsch sein soll, ist mir ein Rätsel. o.ô
 

SilverClaw

Aktives Mitglied
Wirklich....niemand ne Idee? Oder wneigstens ein "benutz doch gefälligst Schema", was ich aber eigentlich nicht wollte, weil DTD doch "schöner" aussah... :oops:
 

taro

Bekanntes Mitglied
Code:
#IMPLIED
macht keinen Sinn, wenn du einen Default-Parameter schon mitgibst - funktioniert auch logischerweise nicht.

Leerzeichen zwischen Elementnamen und Attributauflistungen wichtig

und die DOCTYPE-Deklaration kommt nur in die XML-Datei - macht ja auch keinen Sinn, sich selbst anzugeben ;-)

[XML]<!ELEMENT units (unit+)>
<!ELEMENT unit (health, cost, armor, speed, attack*, heal?)>
<!ATTLIST unit name CDATA #REQUIRED>
<!ELEMENT health (#PCDATA)>
<!ELEMENT cost (#PCDATA)>
<!ELEMENT armor (naked|leather)>
<!ELEMENT speed (immobile|infantry)>
<!ELEMENT attack (#PCDATA)>
<!ATTLIST attack
name CDATA #REQUIRED
image CDATA "none"
damage CDATA "0.0"
range (close|pole) "none"
>[/XML]

Die DTD ist jetzt an sich valide, aber über
Code:
range (close|pole) "none"
solltest du noch einmal nachdenken ... du setzt den Default-Wert auf etwas nicht valides .. dann lass ihn lieber weg, also
Code:
range (close|pole) #IMPLIED
 
Zuletzt bearbeitet:

SilverClaw

Aktives Mitglied
#IMPLIED macht keinen Sinn, wenn du einen Default-Parameter schon mitgibst - funktioniert auch logischerweise nicht
Stimmt, da hab ich wohl was durcheinander gebracht. :rtfm:

und die DOCTYPE-Deklaration kommt nur in die XML-Datei - macht ja auch keinen Sinn, sich selbst anzugeben
Das kam mir auch irgendwie seltsam vor, aber ich war verzweifelt. :oops:

Aber nachdem das erste gefundne war, ergab der Rest auch Sinn...werde das ganze ohnehin nochmal umbauen und im Gegensatz zu den XML-Vorschlägen trotzdem mehr auf Attribute setzen, da ich es etwas sinnlos halte, für sowas wie cost <cost> und </cost> schrieben zu müssen, nur um dann eine Zahl einzutragen...darf man fragen, wie andere das so handhaben?

Groooßes Dankeschön! :applaus:
Ich war schon fast so weit, die Validierung einfach wegzulassen, weil es als einziges beim ebsten Willen nicht geklappt hat...
 

SilverClaw

Aktives Mitglied
Ja Danke, das hatte ich ja schon durch...haate da eher auf persönliche Meinungen gehofft, aber ich werde da sowieso danach gehen, wa smir am besten gefällt. Find es z.B. ganz praktisch, die namen oben gut sichtbar als Attribut zu schreiben, weil man dann direkt sieht, wozu das ganze Element gehört.
 

Ähnliche Java Themen

Neue Themen


Oben