# XML mit DTD prüfen



## SilverClaw (22. Jun 2014)

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. ;(



Spoiler: 
Meine xml-Datei





```
<?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.)



Spoiler: meine DTD bisher





```
<!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"
>
```






Spoiler: mein java-code





```
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.


Spoiler: stacktrace



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 (26. Jun 2014)

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


----------



## taro (27. Jun 2014)

```
#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 
	
	
	
	





```
range (close|pole) "none"
```
 solltest du noch einmal nachdenken ... du setzt den Default-Wert auf etwas nicht valides .. dann lass ihn lieber weg, also 
	
	
	
	





```
range (close|pole) #IMPLIED
```


----------



## SilverClaw (27. Jun 2014)

> #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. 

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...


----------



## taro (28. Jun 2014)

wahrscheinlich gibt es ewig viele Vergleiche Attribute <-> Elemente, spontan verlinke ich mal auf XML Elements vs. Attributes


----------



## SilverClaw (29. Jun 2014)

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.


----------

