Rems Rems - 7 months ago 27
Java Question

Addding reference entity to parse an XML file in JAVA

I am reading an XML file in JAVA like this :

String filepath = xmlFile;
File workFile = new File(filepath);
File fragmentDir = workFile.getParentFile();
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filepath);


And in this xml file there is references like &testRef;

I have an other file where I declared all the entities like this :

<!ENTITY testRef 'hello"'>


The simple solution is to add directly these references in the xml file or add an !ENTITY system "file.ref" but I can't.
Is there a solution where I can tell to my DocumentBuilderFactory : use this file to read the references ?

Thanks.

Edit : I've tried this :

docBuilder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) throws SAXException,IOException {
System.out.println("Resolving");
return new InputSource("file.ref");
}
});


But I keep getting "The entity "testRef" was referenced, but not declared...", the text "Resolving" is not even print. It seems that the document builder doesn't take into account the new resolver.

What am I missing ?

Thanks.

Answer

Use DocumentBuilder's setEntityResolver method.

class Resolver implements EntityResolver {

  public InputSource resolveEntity(String publicId, String systemId) {
  if (systemId.equals("THE_SYSTEM_ID_THAT_YOU_ARE_USING")) {
     System.out.println("Resolving Entity...");
     return new InputSource("YOUR_REFERENCES_XML");
  } else {
     // use the default behaviour
     return null;
  }
  }
}

and then

DocumentBuilder builder = factory.newDocumentBuilder();
Resolver res = new Resolver();
builder.setEntityResolver(res);
Document doc = builder.parse("YOUR XML FILE");

EDIT:

After looking a deeper look at EntityResolver, I see that the entity resolver is ignored if the XML file doesn't declare the Entity Refernce file (which is the problem that you have at hand). However you can adapt below trick to make it work:

static String template =
           "<!DOCTYPE x [ "
         + "<!ENTITY  % entities SYSTEM \"{0}\"> "
         + "<!ENTITY file SYSTEM \"{1}\" >" + "%entities;" + "]>"
         + "<x>&file;</x>";

 private static String createFromTemplate(File entityFile, File xmlFile) {
     return MessageFormat.format(template, entityFile.getAbsolutePath(),
             xmlFile.getAbsolutePath());
 }

 private static File entityFile = new File(<ENTITYFILE>);

 public Document parse(File f) throws JDOMException, IOException {
     String xml = createFromTemplate(entityFile, f);
     SAXBuilder builder = new SAXBuilder();
     Document doc = builder.build(new StringReader(xml));
     Element e = (Element) doc.getRootElement().getChildren().get(0);
     e.detach();
     Document doc2 = new Document(e);
     return doc2;
 }

The ENTITYFILE is the file where the Entity References are declared.

Hope that helps.

Comments