javaxmldom4j

how to use dom4j SAXReader offline?


I would like to work with SAXReader offline, the problem is that SAXReader is verifying the xml accoerding to the DTD. I don't want to change the DTD or anything else in the XML. From searching on this website and other sources I found 2 answers that did not help me:

  1. use EntityResolver to bypass the network call
  2. use setIncludeExternalDTDDeclarations(false)

Example of what I tried to do:

protected Document getPlistDocument() throws MalformedURLException,
DocumentException {
    SAXReader saxReader = new SAXReader();
    saxReader.setIgnoreComments(false);
    saxReader.setIncludeExternalDTDDeclarations(false);
    saxReader.setIncludeInternalDTDDeclarations(true);
    saxReader.setEntityResolver(new MyResolver());
    Document plistDocument = saxReader.read(getDestinationFile().toURI().toURL());
    return plistDocument;
}

public class MyResolver implements EntityResolver {
    public InputSource resolveEntity (String publicId, String systemId)
    {
        if (systemId.equals("http://www.myhost.com/today")) {
            // if we want a custom implementation, return a special input source
            return null;

        } else {
            // use the default behaviour
            return null;
        }
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

I'm still unable to work offline, please advice... thanks

StackTrace:

14:20:44,358 ERROR [ApplicationBuilder] iphone build failed: Resource Manager - Problem handle Root.plist: www.apple.com Nested exception: www.apple.com
com.something.builder.sourcemanager.exception.SourceHandlingException: Resource Manager - Problem handle Root.plist: www.apple.com Nested exception: www.apple.com
****
****
Caused by: org.dom4j.DocumentException: www.apple.com Nested exception: www.apple.com
at org.dom4j.io.SAXReader.read(SAXReader.java:484)
at org.dom4j.io.SAXReader.read(SAXReader.java:291)  
... 10 more

Solution

  • Your entity resolver doesn't handle anything (since it always returns null). Make it return an InputSource to the actual DTD file when the system ID is http://www.apple.com/DTDs/PropertyList-1.0.dtd, since that's the DTD that dom4j tries downloading.

    public class MyResolver implements EntityResolver {
        public InputSource resolveEntity (String publicId, String systemId)
        {
            if (systemId.equals("http://www.apple.com/DTDs/PropertyList-1.0.dtd")) {
                return new InputSource(MyResolver.class.getResourceAsStream("/dtds/PropertyList-1.0.dtd");
            } else {
                // use the default behaviour
                return null;
            }
        }
    }
    

    This implementation, for example, returns the DTD from the classpath (in the package dtds). You just have to download the DTD yourself and bundle it in your app, in the package dtds.