SOLVED! The problem was with the LocalDTDResolver I needed to implement.
(I need this because I do not want the software to connect to the internet to fetch the DTD. I want to have the DTD local because I want a standalone solution. Local validation is required because an internet connection will not be available in my setup.) The LocaDTDResolver was not correctly returning the correct document when asked for by the parser. Specifically it was always returning the DTD when actually another document module referenced by the DTD was asked for. This resulted in duplicate declaration which caused the recursion issue. the DTD is a document in itself that then references other files (called modules) I solved this problem partly by first doing a google search for "Recursive entity reference" and looking for the authoritative official Java forums and found: http://forum.java.sun.com/thread.jspa?threadID=5264261&tstart=90 This was not quite what I needed because it was talking about SAX. HOWEVER the problem was the same. All I needed to do was apply it for DOM. The key was getting the LocalDTDResolver figure out what the Parser wanted from what it was asking for. Here's the code for the resolver and following that the code that uses it to parse. import java.io.File; import java.net.MalformedURLException; import java.net.URI; import org.w3c.dom.ls.LSInput; import org.w3c.dom.ls.LSResourceResolver; public class LocalDTDResolver implements LSResourceResolver { String myLocalDTDFileAsString; URI localDTDFileAsUri; String myLocalDTDPath; LSInput LSInput; public LocalDTDResolver( String localDTDPath, String localSVGDTDFilename ) throws MalformedURLException { myLocalDTDPath = localDTDPath; myLocalDTDFileAsString = localDTDPath + localSVGDTDFilename; LSInput = new LSInput(myLocalDTDFileAsString ); } public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { //Allow the application to resolve external resources. // the occasion where systemId == null // is where the LSParser has finished looking at the // DTD and is now looking at the XML document itself // so at this point, make the systemid the same as the // baseuri - the XML document location if ( systemId == null ) { System.out.println( "systemId:" + systemId ); LSInput.setSystemId( baseURI ); LSInput.setPublicId( null ); LSInput.setBaseURI( baseURI ); return LSInput; } if (systemId.endsWith("mydtd.dtd")) { return LSInput; } else { System.out.println( "myLocalDTDPath + systemId:" + myLocalDTDPath + systemId ); LSInput.setSystemId( myLocalDTDPath + systemId ); return LSInput; } } } /* System.out.println( "\nDEBUG" ); System.out.println( "type: " + type ); System.out.println( "namespaceURI:" + namespaceURI ); System.out.println( "publicId:" + publicId ); System.out.println( "systemId:" + systemId ); System.out.println( "baseURI:" + baseURI ); System.out.println( "\n" ); import java.io.File; import java.io.InputStream; import java.io.Reader; import java.net.URI; import org.w3c.dom.ls.LSInput; public class LSInput implements LSInput { private String myLocalDtdFileAsString; public LSInput( String localDtdFileAsString ) { setSystemId( localDtdFileAsString ); } @Override public String getBaseURI() { // TODO Auto-generated method stub return null; } @Override public InputStream getByteStream() { // TODO Auto-generated method stub return null; } @Override public boolean getCertifiedText() { // TODO Auto-generated method stub return false; } @Override public Reader getCharacterStream() { // TODO Auto-generated method stub return null; } @Override public String getEncoding() { // TODO Auto-generated method stub return null; } @Override public String getPublicId() { // TODO Auto-generated method stub return null; //"-//W3C//DTD SVG 1.1//EN"; } @Override public String getStringData() { // TODO Auto-generated method stub return null; } @Override public String getSystemId() { // TODO Auto-generated method stub URI localDtdFileAsUri = (new File( myLocalDtdFileAsString )).toURI(); return localDtdFileAsUri.toString(); } @Override public void setBaseURI(String arg0) { // TODO Auto-generated method stub } @Override public void setByteStream(InputStream arg0) { // TODO Auto-generated method stub } @Override public void setCertifiedText(boolean arg0) { // TODO Auto-generated method stub } @Override public void setCharacterStream(Reader arg0) { // TODO Auto-generated method stub } @Override public void setEncoding(String arg0) { // TODO Auto-generated method stub } @Override public void setPublicId(String arg0) { // TODO Auto-generated method stub } @Override public void setStringData(String arg0) { // TODO Auto-generated method stub } @Override public void setSystemId( String localDtdFileAsString ) { myLocalDtdFileAsString = localDtdFileAsString; } } // part based on Oreilly Java and XML book File file = new File("C:\\myfile.svg"); URI localFileAsUri = file.toURI(); DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance( ); DOMImplementationLS lsImpl = (DOMImplementationLS)registry.getDOMImplementation("LS"); LSParser parser = lsImpl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); // Set options on the parser DOMConfiguration config = parser.getDomConfig( ); config.setParameter("validate", Boolean.TRUE); config.setParameter("resource-resolver", LocalDTDResolver ); org.w3c.dom.Document doc = parser.parseURI(localFileAsUri.toString()); -- View this message in context: http://www.nabble.com/Using-LSParser-with-Local-DTD-gives-exception%3A-Recursive-entity-reference-%22-svg-framework.mod%22-tp16002292p16023916.html Sent from the Xerces - J - Users mailing list archive at Nabble.com. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]