Oded Regev
Oded Regev

Reputation: 4405

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

Upvotes: 4

Views: 4370

Answers (4)

user
user

Reputation: 309

I use NoOpEntityResolver disable online dtd, see code in this website: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#no-op-entityresolver

Upvotes: -1

Aerthel
Aerthel

Reputation: 659

As an option, if you want to just use SAXReader offline, disable its external DTD fetching via the http://apache.org/xml/features/nonvalidating/load-external-dtd Xerces feature.

According Xerces features documentation, setting this to false makes SAXReader ignore the external DTD completely.

This SO answer has a code example.

Upvotes: 0

craigmj
craigmj

Reputation: 5067

Note, too, that you're not actually validating against the DTD. To accomplish that, you need to do:

SAXReader saxReader = new SAXReader(true);

Otherwise JB's right - he got in 3 mins before me!

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691625

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.

Upvotes: 5

Related Questions