我尝试针对java中的相对XSD文件验证某些XML
输入文件temp.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<tagname:b
xmlns:tagname="http://my_namespace.org/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://my_namespace.org/v1 ./local_xsd_file.xsd">
</tagname>
java source:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(true);
factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setErrorHandler(new RaiseOnErrorHandler());
builder.parse(new InputSource(new FileInputStream(filename)));
public static class RaiseOnErrorHandler implements ErrorHandler {
public void warning(SAXParseException e) throws SAXException {
throw new RuntimeException(e);
}
public void error(SAXParseException e) throws SAXException {
throw new RuntimeException(e);
}
public void fatalError(SAXParseException e) throws SAXException {
throw new RuntimeException(e);
}
}
本地文件local_xsd_file.xsd
存在且似乎未被阅读。
错误消息
java.lang.RuntimeException: org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 85; schema_reference.4: Failed to read schema document './local_xsd_file.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 org.XX$RaiseOnErrorHandler.warning(DigitalFileWriterTest.java:1114)
at org.apache.xerces.util.ErrorHandlerWrapper.warning(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.xs.traversers.XSDHandler.reportSchemaWarning(Unknown Source)
at org.apache.xerces.impl.xs.traversers.XSDHandler.getSchemaDocument(Unknown Source)
at org.apache.xerces.impl.xs.traversers.XSDHandler.parseSchema(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaLoader.loadSchema(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.findSchemaGrammar(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.handleStartElement(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.startElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
... 50 more
我还尝试使用file://local_xsd_file.xsd
和file://./local_xsd_file.xsd
(should为possible)作为schemaLocation
,所有结果都相同。如果我使用&#34;绝对路径&#34;像file:///full/path/to/local_xsd_file.xsd
那样可行。如果我使用URL作为架构的位置,它会从该服务器读取它们并且工作正常。
将我当前的工作目录更改为local_xsd_file.xsd存在的目录将使其正常工作,所以显然这可以工作但只相对于您当前的工作目录?
是否可以在java中使用相对路径进行验证?感觉就像是一个实现细节?
答案 0 :(得分:1)
当您构建这样的文档时:
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setErrorHandler(new RaiseOnErrorHandler());
builder.parse(new InputSource(new FileInputStream(filename)));
文档的基本URI未知(因为构建器只看到InputStream
,并且无法发现它正在读取特定文件)。尝试使用可以建立基URI的parse()
方法之一,例如parse(file.toString())
或saxParser.parse(file, (DefaultHandler) null);
。
没有基本URI,没有合理的方法来解析相对URI。系统可能使用当前目录(这似乎在这里发生)或者它可能报告错误。
答案 1 :(得分:0)
对于追随者,如果您正在使用外部模式文件进行验证,那么似乎也可以,只需避免先将其更改为字符串,例如:
public static void verifyMatchesXsd(File xmlFileToTest, File schemaFile) throws IOException, SAXException {
Source xmlFile = new StreamSource(xmlFileToTest);
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(schemaFile);
javax.xml.validation.Validator validator = schema.newValidator();
validator.validate(xmlFile);
}
或版本,而不必指定外部XSD的位置(它使用内部XSD):
private void assertMatchesAnyXsdsMentioned(File xmlFileLocation) throws SAXException, IOException {
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema();
Validator validator = schema.newValidator();
Source xmlSource = new StreamSource(xmlFileLocation);
validator.validate(xmlSource);
}
您也许还可以指定自己的resource resolver,让它也知道您想要哪个子目录...
Sax解析器版本:
static void assertMatchesInternalXsd(File inputFile) throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setValidating(true);
spf.setNamespaceAware(true);
SAXParser saxParser = spf.newSAXParser();
saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
XMLReader reader = saxParser.getXMLReader();
reader.setErrorHandler(new RaiseOnErrorHandler());
saxParser.parse(inputFile, (DefaultHandler) null);
}