Validating XML on XSD in Java / Getting Schema Binding

How can I validate an XML file using XSD in Java? We do not know the circuit in advance. I would like to get schemaLocation , load XSD, cache it, and then do the actual check.

The problem is that with the javax.xml.parsers.DocumentBuilder / DocumentBuilderFactory classes I cannot grab hold of schemaLocation in advance. What is the trick for this? What classes should I look at?

Maybe there is a more suitable API that I can use? The whole problem is that we need to dynamically check, without (necessarily) having local XSD.

How can I get the schemaLocation URL defined in the XSD file?

I know that you can set functions / attributes, but that is another matter. I need to get schemaLocation from XSD first.

Please advise!

+5
java xml-parsing xsd xml-validation
source share
1 answer

Given that you are using Xerces (or the default JDK), did you try setting this function to true in factory: http://apache.org/xml/features/validation/schema . There are other functions that you can play with regards to schemes: http://xerces.apache.org/xerces2-j/features.html

UPDATE 2 (for caching):

Deploy org.w3c.dom.ls.LSResourceResolver and set it to SchemaFactory using the setResourceResolver method. This resolver will either get the circuit from the cache or retrieve it from where it relates.

UPDATE 3:

LSResourceresolver example (which I think would be a good starting point for you):

 /** * Resolves resources from a base URL */ public class URLBasedResourceResolver implements LSResourceResolver { private static final Logger log = LoggerFactory .getLogger(URLBasedResourceResolver.class); private final URI base; private final Map<URI, String> nsmap; public URLBasedResourceResolver(URL base, Map<URI, String> nsmap) throws URISyntaxException { super(); this.base = base.toURI(); this.nsmap = nsmap; } @Override public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { if (log.isDebugEnabled()) { String msg = String .format("Resolve: type=%s, ns=%s, publicId=%s, systemId=%s, baseUri=%s.", type, namespaceURI, publicId, systemId, baseURI); log.debug(msg); } if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) { if (namespaceURI != null) { try { URI ns = new URI(namespaceURI); if (nsmap.containsKey(ns)) return new MyLSInput(base.resolve(nsmap.get(ns))); } catch (URISyntaxException e) { // ok } } } return null; } } 

The implementation of MyLSInput is really boring:

 class MyLSInput implements LSInput { private final URI url; public MyLSInput(URI url) { super(); this.url = url; } @Override public Reader getCharacterStream() { return null; } @Override public void setCharacterStream(Reader characterStream) { } @Override public InputStream getByteStream() { return null; } @Override public void setByteStream(InputStream byteStream) { } @Override public String getStringData() { return null; } @Override public void setStringData(String stringData) { } @Override public String getSystemId() { return url.toASCIIString(); } @Override public void setSystemId(String systemId) { } @Override public String getPublicId() { return null; } @Override public void setPublicId(String publicId) { } @Override public String getBaseURI() { return null; } @Override public void setBaseURI(String baseURI) { } @Override public String getEncoding() { return null; } @Override public void setEncoding(String encoding) { } @Override public boolean getCertifiedText() { return false; } @Override public void setCertifiedText(boolean certifiedText) { } } 
+4
source share

All Articles