问题
The picture is self explanatory. When I validate the document using identical process in CMD, the document is declared valid. It is valid when checked manually.
The jar file generates this message:
Invalid
schema_reference.4: Failed to read schema document 'E:/XML and Java/Pro XML Development with Java/schema.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>.
The question is: WHY?
The process of validating an XML using XSD via a JAR file is necessary for the application I am making.
SSCCE
package xml;
import javax.swing.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.*;
public class JarValidator extends JFrame{
JTextArea area = new JTextArea();
JScrollPane pane = new JScrollPane(area);
SAXParserFactory factory;
SAXParser parser;
final String USER_DIR = System.getProperty("user.dir").replace('\\','/').concat("/");
final String XML_FILE_NAME = "helloWorld.xml";
final String SCHEMA_FILE_NAME = "schema.xsd";
final String JAXP_SCHEMA_LANGUAGE_PROPERTY =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage";
final String W3_SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema";
final String JAXP_SCHEMA_SOURCE_PROPERTY = "http://java.sun.com/xml/jaxp/properties/schemaSource";
public JarValidator(){
this.getContentPane().add(pane);
this.pack();
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
try{
factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
parser = factory.newSAXParser();
parser.setProperty(JAXP_SCHEMA_LANGUAGE_PROPERTY, W3_SCHEMA_LANGUAGE);
parser.setProperty(JAXP_SCHEMA_SOURCE_PROPERTY,
USER_DIR+SCHEMA_FILE_NAME);
ErrorHandler handler = new ErrorHandler();
parser.parse(new java.io.File(USER_DIR+XML_FILE_NAME), handler);
if(handler.errorOccured == true){
area.append("Invalid \n");
area.append(handler.ex.getMessage());
}else{
area.append("Valid");
}
}catch(SAXException e){
area.append(e.getMessage());
}catch(ParserConfigurationException e){
area.append(e.getMessage());
}catch(java.io.IOException e){
area.append(e.getMessage());
}catch(Exception e){
area.append(e.getMessage());
}
}
private class ErrorHandler extends DefaultHandler{
public SAXParseException ex = null;
public boolean errorOccured = false;
@Override
public void error(SAXParseException ex) {
this.ex = ex;
errorOccured = true;
}
@Override
public void fatalError(SAXParseException ex){
this.ex = ex;
errorOccured = true;
}
@Override
public void warning(SAXParseException ex){
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override public void run(){
new JarValidator();
}
});
}
}
On a directory structure with no spaces in the name of any folders, the same error.
Invalid
schema_reference.4: Failed to read schema document 'E:/test/schema.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>.
Just thought I might add:
I am on a Windows 7 32 bit machine.
The JAR is in the same file as the XML and XSD hence user.dir
works.
回答1:
In the Java XML world, a String
parameter rarely (perhaps never) refers to a filename. Instead, it usually is expected to contain a URL. Given that, I would replace this code:
parser.setProperty(JAXP_SCHEMA_SOURCE_PROPERTY, USER_DIR+SCHEMA_FILE_NAME);
By this code (which also avoids the separator munging and string concatenation):
File userDir = new File(System.getProperty("user.dir"));
File schemaFile = new File(userDir, SCHEMA_FILE_NAME);
parser.setProperty(JAXP_SCHEMA_SOURCE_PROPERTY, schemaFile);
Two caveats:
- I simply typed this; it may contain typos.
- I did not take the time to check documentation for the property. However, it's how all the other JDK XML APIs work, so I feel confident that it's correct. Whatever documentation you're using to get the property name should give you more information.
来源:https://stackoverflow.com/questions/16615773/sax-parsing-through-a-jar-file-declares-xml-document-invalid