M
Mark Wright
I'm using java 1.4 and xerces and I'm having problems validating XML.
I want to be able to override XSD retrieval (eventually, they will be
in a JAR file). This works fine when the XSD I'm validating doesn't
"import" other XSDs - I just assign a custom entity resolver. But if
those XSDs then import other XSDs, the entity resolver isn't called
for the imported XSD. Xerces tries to resolve the schemaLocation as a
URL, without letting my code redirect the reference.
Is there a solution to this problem?
This is the code I'm using:
===================================================
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.util.Iterator;
public class validate
{
static public class ResolverImpl implements EntityResolver
{
public InputSource resolveEntity(String publicId, String
systemId)
throws SAXException, IOException
{
System.out.println("resolving " + systemId + " : " +
publicId);
System.out.flush();
return new InputSource(new FileInputStream(
"c:\\somedirectory\\" + systemId));
}
}
static class ErrorHandlerImpl implements ErrorHandler
{
List errors = new LinkedList();
public void fatalError(SAXParseException e)
{
errors.add(e);
}
public void warning(SAXParseException e)
{
}
public void error(SAXParseException e)
{
errors.add(e);
}
boolean hasErrors()
{
if (errors.size() > 0)
return true;
else
return false;
}
void printErrors()
{
Iterator it = errors.iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
static void validateContents(byte[] contents)
{
try
{
ErrorHandlerImpl handler = new ErrorHandlerImpl();
ByteArrayInputStream stream = new
ByteArrayInputStream(contents);
DocumentBuilderFactory docBuilderFactory
= DocumentBuilderFactory.newInstance();
docBuilderFactory.setValidating(true);
docBuilderFactory.setNamespaceAware(true);
DocumentBuilder docBuilder =
docBuilderFactory.newDocumentBuilder();
docBuilder.setErrorHandler(handler);
docBuilder.setEntityResolver(new ResolverImpl());
Document document = docBuilder.parse(stream);
Element rootElement = document.getDocumentElement();
System.out.println("errors = " + handler.hasErrors());
handler.printErrors();
}
catch (ParserConfigurationException e)
{
System.out.println("parse error:" + e);
}
catch (SAXException e)
{
System.out.println("parse error:" + e);
}
catch (IOException e)
{
System.out.println("parse error:" + e);
}
}
public static void main (String[] args)
{
try
{
validateContents(Util.readFile(args[0]));
}
catch (Exception e)
{
System.out.println("exception:" + e);
}
}
}
I want to be able to override XSD retrieval (eventually, they will be
in a JAR file). This works fine when the XSD I'm validating doesn't
"import" other XSDs - I just assign a custom entity resolver. But if
those XSDs then import other XSDs, the entity resolver isn't called
for the imported XSD. Xerces tries to resolve the schemaLocation as a
URL, without letting my code redirect the reference.
Is there a solution to this problem?
This is the code I'm using:
===================================================
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.util.Iterator;
public class validate
{
static public class ResolverImpl implements EntityResolver
{
public InputSource resolveEntity(String publicId, String
systemId)
throws SAXException, IOException
{
System.out.println("resolving " + systemId + " : " +
publicId);
System.out.flush();
return new InputSource(new FileInputStream(
"c:\\somedirectory\\" + systemId));
}
}
static class ErrorHandlerImpl implements ErrorHandler
{
List errors = new LinkedList();
public void fatalError(SAXParseException e)
{
errors.add(e);
}
public void warning(SAXParseException e)
{
}
public void error(SAXParseException e)
{
errors.add(e);
}
boolean hasErrors()
{
if (errors.size() > 0)
return true;
else
return false;
}
void printErrors()
{
Iterator it = errors.iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
static void validateContents(byte[] contents)
{
try
{
ErrorHandlerImpl handler = new ErrorHandlerImpl();
ByteArrayInputStream stream = new
ByteArrayInputStream(contents);
DocumentBuilderFactory docBuilderFactory
= DocumentBuilderFactory.newInstance();
docBuilderFactory.setValidating(true);
docBuilderFactory.setNamespaceAware(true);
DocumentBuilder docBuilder =
docBuilderFactory.newDocumentBuilder();
docBuilder.setErrorHandler(handler);
docBuilder.setEntityResolver(new ResolverImpl());
Document document = docBuilder.parse(stream);
Element rootElement = document.getDocumentElement();
System.out.println("errors = " + handler.hasErrors());
handler.printErrors();
}
catch (ParserConfigurationException e)
{
System.out.println("parse error:" + e);
}
catch (SAXException e)
{
System.out.println("parse error:" + e);
}
catch (IOException e)
{
System.out.println("parse error:" + e);
}
}
public static void main (String[] args)
{
try
{
validateContents(Util.readFile(args[0]));
}
catch (Exception e)
{
System.out.println("exception:" + e);
}
}
}