Так как это популярный вопрос, я укажу, что java также может проверять на соответствие «упомянутым» xsd, например, если сам файл .xml определяет XSD в заголовке, используя xsi:SchemaLocation
или xsi:noNamespaceSchemaLocation
(или xsi для определенных пространств имен) ex :
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.example.com/document.xsd">
...
или SchemaLocation (всегда список отображений пространства имен в xsd)
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="http://www.example.com/my_namespace http://www.example.com/document.xsd">
...
Здесь также работают и другие ответы, потому что файлы .xsd «сопоставляются» с пространствами имен, объявленными в файле .xml, потому что они объявляют пространство имен, и если оно совпадает с пространством имен в файле .xml, вы ' хорошо. Но иногда удобно иметь пользовательский resolver ...
Из javadocs: «Если вы создаете схему без указания URL, файла или источника, то язык Java создает тот, который просматривает проверяемый документ, чтобы найти схему, которую он должен использовать. Например:»
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
и это работает для нескольких пространств имен и т. Д.
Проблема с этим подходом состоит в том, что xmlsns:xsi
, вероятно, является сетевым местоположением, поэтому он по умолчанию будет выходить из сети и попадать в сеть при каждой проверке, не всегда оптимальной.
Вот пример, который проверяет XML-файл по любому XSD-файлу, на который он ссылается (даже если он должен извлечь их из сети):
public static void verifyValidatesInternalXsd(String filename) throws Exception {
InputStream xmlStream = new new FileInputStream(filename);
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(xmlStream));
xmlStream.close();
}
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);
}
}
Вы можете избежать извлечения ссылочных XSD из сети, даже несмотря на то, что ссылки на xml-файлы ссылаются на URL, указав xsd вручную (см. Некоторые другие ответы здесь) или воспользовавшись распознавателем в стиле «XML каталог» . Spring, по-видимому, также может перехватывать запросы URL-адресов для предоставления локальных файлов для проверки. Или вы можете установить свои собственные с помощью setResourceResolver , например:
Source xmlFile = new StreamSource(xmlFileLocation);
SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema();
Validator validator = schema.newValidator();
validator.setResourceResolver(new LSResourceResolver() {
@Override
public LSInput resolveResource(String type, String namespaceURI,
String publicId, String systemId, String baseURI) {
InputSource is = new InputSource(
getClass().getResourceAsStream(
"some_local_file_in_the_jar.xsd"));
// or lookup by URI, etc...
return new Input(is); // for class Input see
// https://stackoverflow.com/a/2342859/32453
}
});
validator.validate(xmlFile);
См. Также здесь для другого учебника.
Я считаю, что по умолчанию используется синтаксический анализ DOM, вы можете сделать что-то похожее с SAX-парсером, который также проверяет saxReader.setEntityResolver(your_resolver_here);