# DTD aus Classpath



## matches (5. Sep 2008)

Hallo,

ich habe ein Problem beim Validieren einer XML-Datei anhand einer DTD. Der Name der DTD ist im Header der XML-Datei angegeben.

Ich parse die XML-Datei mit einem DOM-Parser.

Der DOM-Parser sucht die DTD allerdings immer im selben Verzeichnis, in dem das XML liegt.

Wie kann ich dem Parser beibringen, dass er die DTD im Classpath suchen soll?


matches


----------



## Ladi (5. Sep 2008)

Hallo matches,

kannst Du vielleicht den Header deiner XML-Datei einbinden, damit wir Deine genaue Formulierung sehen können?

Gruß
Ladi


----------



## Ladi (5. Sep 2008)

Hallo matches,

habe ein wenig gegoogelt und habe eine Lösung gefunden. Diese heißt EntityResolver. Ein EntityResolver wird vom Parser aufgerufen um eine Entity zu finden und mann kann hier das implizite Verhalten übersteuern.

Beispiel:
DTD - im Programmverzeichnis abgelegt


```
<?xml version="1.0" encoding="UTF-8"?>

<!ELEMENT MyXml (MyNode)*>

<!ELEMENT MyNode (#PCDATA)>
```

XML - am beliebigen Platz abgelegt


```
<?xml version="1.0"?>
<!DOCTYPE MyXml SYSTEM "http://de.petera.xmlTest/MyXml.dtd">

<MyXml>
	<MyNode>node 1</MyNode>
	<MyNode>node 2</MyNode>
</MyXml>
```

Der folgende Kode gaukelt dem Parser einen InputStream mit der im Anwendungsverzeichnis abgelegten dtd immer, wenn er den System-Id "http://de.petera.xmlTest/MyXml.dtd" auflösen will.


```
package de.petera.xmlTest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class XmlTest {

	public static void main(String[] args) throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setValidating(true);
		DocumentBuilder builder = factory.newDocumentBuilder();
		builder.setEntityResolver(new MyResolver());
		Document doc = builder.parse(new File("d:/MyXml.xml"));
		
		NodeList elements = doc.getDocumentElement().getElementsByTagName("MyNode");
		
		for (int i=0;i<elements.getLength(); i++) {
			System.out.println(elements.item(i).getNodeValue());
		}
		
	}
	
}

class MyResolver implements EntityResolver {
	public InputSource resolveEntity(String publicId, String systemId)
			throws SAXException, IOException {

		if (systemId.equals("http://de.petera.xmlTest/MyXml.dtd")) {
			return new InputSource(new FileInputStream("MyXml.dtd"));
		} else {
			// use the default behaviour
			return null;
		}
	}
}
```

Gruß
Ladi


----------



## matches (5. Sep 2008)

Hallo,

so sieht der Header aus:


```
<?xml version="1.0" encoding="WINDOWS-1252"?>
<!DOCTYPE product PUBLIC "-//name//DTD specification//EN" "dsf.dtd">
```

matches


----------



## Ladi (5. Sep 2008)

Hallo matches,

für Antwort siehe meinen Vorherigen Post. In Deinem Fall würde die resolveEntity funktion halt den Attribut publicId auswerten.

Gruß
Ladi


----------



## matches (5. Sep 2008)

Hallo Ladi,

top, es funktioniert.

Vielen Dank für deine Hilfe.

Grüße matches


----------

