问题
I have servlet which uses utility packaged in .jar archive:
@Override
public void init() throws ServletException {
...
try (InputStream stream = getClass().getResourceAsStream("/fileToParse.xml")) {
App.check(stream);
} catch (Exception e) {
throw new ServletException(e);
}
...
}
This utility takes xml file stream, performs validation against xsd schema and parses it:
public class App {
private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
...
public static void check(InputStream stream) {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(true);
MyHandler handler = new MyHandler();
try {
SAXParser sp = spf.newSAXParser();
sp.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
XMLReader rdr = sp.getXMLReader();
rdr.setContentHandler(handler);
rdr.setErrorHandler(new MyErrorHandler());
rdr.parse(new InputSource(stream));
}
...
}
...
}
xsd file starts with:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.mydomain.org"
elementFormDefault="qualified"
xmlns:t="http://www.mydomain.org">
<xs:element name="appContext">
...
xml file:
<?xml version="1.0" encoding="UTF-8"?>
<appContext xmlns="http://www.mydomain.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mydomain.org appContext.xsd">
...
.war structure:
css/
js/
WEB-INF/
classes/
mypackage/
MyServlet.class
fileToParse.xml
lib/
App.jar
web.xml
App.jar structure:
mypackage2/
App.class
appContext.xsd
Servlet Init method throws exception:
...
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_21]
at java.lang.Thread.run(Thread.java:722) [na:1.7.0_21]
Caused by: java.io.FileNotFoundException: /PATH_TO_TOMCAT/bin/appContext.xsd (No such file or directory)
at java.io.FileInputStream.open(Native Method) ~[na:1.7.0_21]
at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[na:1.7.0_21]
How I can specify to SAXParser where is xsd schema needed to validate xml file?
P.S. Sorry for my bad English
UPD:
I'm trying to add this property:
private static final String JAXP_SCHEMA_SOURCE =
"http://java.sun.com/xml/jaxp/properties/schemaSource";
....
public static void check(InputStream stream) {
...
try {
...
sp.setProperty(JAXP_SCHEMA_SOURCE, new File(getPath("/appContext.xsd")));
...
}
}
public static String getPath(String path) {
return App.class.getResource(path).toString();
}
Now I have this exception:
ERROR mypackage2.App - Error: URI=null Line=5: schema_reference.4: Failed to read schema document 'jar:file:/PATH_TO_TOMCAT/webapps/myapp/WEB-INF/lib/App.jar!/appContext.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'jar:file:/PATH_TO_TOMCAT/webapps/myapp/WEB-INF/lib/App.jar!/appContext.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198) ~[na:1.7.0_21]
UPD2: With "classpath:appContext.xsd" in xml file:
WARN mypackage.App - Warning: URI=null Line=5: schema_reference.4: Failed to read schema document 'classpath:appContext.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'classpath:appContext.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198) ~[na:1.7.0_21]
...
at java.lang.Thread.run(Thread.java:722) [na:1.7.0_21]
Caused by: java.net.MalformedURLException: unknown protocol: classpath
at java.net.URL.<init>(URL.java:592) ~[na:1.7.0_21
;;;
回答1:
Try setting the schema source as InputStream
directly
public static void check(InputStream stream) {
...
try {
...
sp.setProperty(JAXP_SCHEMA_SOURCE, getInputStream("/appContext.xsd")));
...
}
}
public static InputStream getInputStream(String path) {
return SAXLoader.class.getResourceAsStream(path);
}
Check if setting this property works after removing the XSD reference from the XML file. If not, check if the property works or not by simply testing with the XSD located outside the jar and its absolute path passed as a File
reference as you're doing right now.
回答2:
Problem solved:
public class App {
...
public static void check(InputStream stream) {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(true);
MyHandler handler = new MyHandler();
try (InputStream schemaStream = App.class.getResourceAsStream("/appContext.xsd")) {
SAXParser sp = spf.newSAXParser();
sp.setProperty(JAXPConstants.JAXP_SCHEMA_LANGUAGE, JAXPConstants.W3C_XML_SCHEMA);
sp.setProperty(JAXPConstants.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
XMLReader rdr = sp.getXMLReader();
rdr.setContentHandler(handler);
rdr.setErrorHandler(new MyErrorHandler());
rdr.parse(new InputSource(stream));
}
...
}
...
}
来源:https://stackoverflow.com/questions/18579837/java-servlets-xml-validation-against-xsd