Java servlet:针对xsd的xml验证

Java servlet:针对xsd的xml验证,java,xml,servlets,xsd,jaxp,Java,Xml,Servlets,Xsd,Jaxp,我有一个servlet,它使用打包在.jar存档中的实用程序: @Override public void init() throws ServletException { ... try (InputStream stream = getClass().getResourceAsStream("/fileToParse.xml")) { App.check(stream); } catch (Exception e) { throw ne

我有一个servlet,它使用打包在.jar存档中的实用程序:

@Override
public void init() throws ServletException {
    ...
    try (InputStream stream = getClass().getResourceAsStream("/fileToParse.xml")) {
        App.check(stream);
    } catch (Exception e) {
        throw new ServletException(e);
    }
    ...
}
此实用程序获取xml文件流,对xsd架构执行验证并对其进行解析:

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文件以以下内容开头:

<?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">
        ...
App.jar结构:

css/
js/
WEB-INF/
    classes/
        mypackage/
            MyServlet.class
        fileToParse.xml
    lib/
        App.jar
    web.xml
mypackage2/
    App.class
appContext.xsd
Servlet Init方法引发异常:

...
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]
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]
现在我有一个例外:

...
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]
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]
ERROR mypackage2.App-ERROR:URI=null Line=5:schema\u reference.4:无法读取架构文档'jar:file:/PATH\u to\u TOMCAT/webapps/myapp/WEB-INF/lib/App.jar/appContext.xsd',因为1)找不到文档;2) 文件无法读取;3) 文档的根元素不是。
org.xml.sax.SAXParseException:schema_reference.4:无法读取模式文档'jar:file:/PATH_to_TOMCAT/webapps/myapp/WEB-INF/lib/App.jar/appContext.xsd',因为1)找不到文档;2) 文件无法读取;3) 文档的根元素不是。
在com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)~[na:1.7.021]
UPD2: 在xml文件中使用“classpath:appContext.xsd”:

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
;;;
WARN mypackage.App-Warning:URI=null Line=5:schema_reference.4:未能读取架构文档'classpath:appContext.xsd',因为1)找不到该文档;2) 文件无法读取;3) 文档的根元素不是。
org.xml.sax.SAXParseException:schema_reference.4:未能读取架构文档'classpath:appContext.xsd',因为1)找不到该文档;2) 文件无法读取;3) 文档的根元素不是。
在com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)~[na:1.7.021]
...
在java.lang.Thread.run(Thread.java:722)[na:1.7.0_21]
原因:java.net.MalformedURLException:未知协议:类路径
在java.net.URL.(URL.java:592)~[na:1.7.0\u21
;;;
尝试直接将架构源设置为
InputStream

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);
}
在从XML文件中删除XSD引用后,检查设置此属性是否有效。如果无效,只需使用位于jar外部的XSD进行测试,并像您现在所做的那样将其绝对路径作为
文件
引用传递,即可检查此属性是否有效。

问题已解决:

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));
        }
        ...
    }
    ...
}

谢谢您的回答。不幸的是,现在我有一个异常(UPD2)@chepiov无法工作。我错误地认为这是一个Spring应用程序(
classpath
protocol无法识别)。但是,您可以尝试我的更新并让我知道吗?