The copy of resolver.jar here is actually a slightly modified version of version 1.2 of Apache XML Commons Resolver. I believe it trips up on a bug in JDK 5 (apaprently not found in 1.4 or 6) wherein java.net.URL.toString() returns an invalid URL representation beginning with only "file://" instead of "file:/" or "file:///", and when reparsed later into a URL in the code it yields an UnknownHostException, which prevents the library from using DTDs stored on the local file system. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6351751 My workaround is to add code before this line in CatalogResolver.resolveEntity(): URL url = new URL(resolved); Like so: if (resolved.startsWith("file://") && !resolved.startsWith("file:///")) { resolved = "file:///" + resolved.substring(7); } URL url = new URL(resolved); Also, if you are using Java 6 to compile for this project, the Ant build file resolver.xml should be modified so that targets specify source="1.5" and target="1.5". Finally we realized this library isn't designed to load resources from the classpath. A little more hacking does it. In the same method, URL url = new URL(resolved); InputStream iStream = url.openStream(); Should change to: URL url = new URL(resolved); InputStream iStream = null; try { iStream = url.openStream(); } catch (FileNotFoundException fnfe) { // also added by srowen // If file not available, look in classpath resolved = getResourceFromAbsoluteFilename(resolved); iStream = getClass().getResourceAsStream("/" + resolved); } ... private static String getResourceFromAbsoluteFilename(final String systemId) throws MalformedURLException { // systemId is something like file:///foo/bar/dtd/stuff.dtd // This will generate something like file:///foo/bar/: final String baseFileName = FileURL.makeURL("").toString(); // We need to pick out "dtd/stuff.dtd", but can't do it with a simple substring call. // There are issues with, for example, how many slashes follow the file: protocol final int systemIdSlashEnd = findEndOfSlashes(systemId); final int baseFileNameSlashEnd = findEndOfSlashes(baseFileName); final int prefixLength = baseFileName.length() - baseFileNameSlashEnd; return systemId.substring(systemIdSlashEnd + prefixLength); } private static int findEndOfSlashes(final String s) { int i = 0; while (s.charAt(i) != '/') { i++; } while (s.charAt(i) == '/') { i++; } return i; } -srowen