Skip to content

org.xmlresolver.XMLResolver.getEntityResolver() always returns a org.xml.sax.ext.EntityResolver2 #183

@JFK-DXML

Description

@JFK-DXML

(This is with XmlResolver 6.0.2)

If I pass an org.apache.xerces.parsers.SAXParser an org.xml.sax.ext.EntityResolver2 interface it will call EntityResolver2.getExternalSubset(String, String) if the XML file has no DTD declaration for example.

If the EntityResolver2 interface is implemented by org.xmlresolver.adapters.SAXAdapter and there is no entry for the Document element root name in the catalog and org.xmlresolver.ResolverFeature.ALWAYS_RESOLVE is set to true (the default) SAXAdapter will return the document which is being parsed (if that document has an associated URI in the InputSource). Apart from not being what is intended, this causes an error to be thrown by the parser because the XML input file is not a DTD, and we get something like

net.sf.saxon.s9api.SaxonApiException: org.xml.sax.SAXParseException; systemId: file:///Users/johnf/dev26/core/xml-compare-main/target/test-classes/white-box/unstaged-data/xmlresolver/EntityResolver2_1.xml; lineNumber: 2; columnNumber: 2; The markup declarations contained or pointed to by the document type declaration must be well-formed.

Since org.xmlresolver.XMLResolver.getEntityResolver() is implemented by calling org.xmlresolver.XMLResolver.getEntityResolver2() and implements both org.xml.sax.ext.EntityResolver2 and org.xml.sax.EntityResolver interfaces, we can't avoid using an EntityResolver2 without wrapping inside a class that doesn't implement EntityResolver2. The other choice is to turn ALWAYS_RESOLVE off, which we can't do in other circumstances, and since ours is a third party JAR we can't edit the catalogs that are used.

(The old catalog resolver only implemented EntityResolver and therefore did not have this problem.)

`

import java.io.File;
import java.io.IOException;
import java.io.StringReader;

import javax.xml.transform.sax.SAXSource;

import org.apache.xerces.parsers.SAXParser;
import org.testng.annotations.Test;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.EntityResolver2;
import org.xmlresolver.ResolverFeature;
import org.xmlresolver.XMLResolver;
import org.xmlresolver.XMLResolverConfiguration;

import net.sf.saxon.s9api.DocumentBuilder;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.XdmNode;


public void testEntityResolver2_withURI() throws Exception {
    File testFile = new File(DataDir, "EntityResolver2_1.xml");
    InputSource is= new InputSource(testFile.getAbsolutePath());    
    Processor p = new Processor(true);
    DocumentBuilder docBuilder = p.newDocumentBuilder();
    SAXParser parser= new SAXParser();

    XMLResolverConfiguration resolverConfig = new XMLResolverConfiguration();
    resolverConfig.setFeature(ResolverFeature.ALWAYS_RESOLVE, true);
    XMLResolver resolver = new XMLResolver(resolverConfig);

    parser.setEntityResolver(resolver.getEntityResolver());

    XdmNode n= docBuilder.build(new SAXSource(parser, is));
  }`

The file is simply

<StandardXmlRootElement/>

By wrapping I mean something like the following

`

private static final class MaskEntityResolver2Functionality implements EntityResolver {
  private final EntityResolver2 wrappedResolver;

    private MaskEntityResolver2Functionality(EntityResolver2 wrappedResolver) {
      assert wrappedResolver!=null : "Must wrap something";
      this.wrappedResolver= wrappedResolver;
    }

    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
      return wrappedResolver.resolveEntity(publicId, systemId);
   }

}
`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions