Вопрос-ответ

How to validate an XML file against an XSD file?

Как проверить соответствие XML-файла XSD-файлу?

Я создаю несколько XML-файлов, которые должны соответствовать предоставленному мне xsd-файлу. Как я должен проверить их соответствие?

Переведено автоматически
Ответ 1

Библиотека Java runtime поддерживает проверку. В последний раз, когда я проверял это, это был синтаксический анализатор Apache Xerces under the covers . Вероятно, вам следует использовать javax.xml.validation.Валидатор.

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;
import java.net.URL;
import org.xml.sax.SAXException;
//import java.io.File; // if you use File
import java.io.IOException;
...
URL schemaFile = new URL("http://host:port/filename.xsd");
// webapp example xsd:
// URL schemaFile = new URL("http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd");
// local file example:
// File schemaFile = new File("/location/to/localfile.xsd"); // etc.
Source xmlFile = new StreamSource(new File("web.xml"));
SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try {
Schema schema = schemaFactory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.validate(xmlFile);
System.out.println(xmlFile.getSystemId() + " is valid");
} catch (SAXException e) {
System.out.println(xmlFile.getSystemId() + " is NOT valid reason:" + e);
} catch (IOException e) {}

Константа фабрики схемы - это строка, http://www.w3.org/2001/XMLSchema которая определяет XSDSDS. Приведенный выше код проверяет дескриптор развертывания WAR на соответствие URL http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd но вы могли бы так же легко проверить на соответствие локальному файлу.

Вам не следует использовать DOMParser для проверки документа (если только вашей целью в любом случае не является создание объектной модели документа). При разборе документа начнется создание DOM-объектов - расточительно, если вы не собираетесь их использовать.

Ответ 2

Вот как это сделать с помощью Xerces2. Руководство по этому, здесь (см. регистрацию).

Авторство оригинала: нагло скопировано отсюда:

import org.apache.xerces.parsers.DOMParser;
import java.io.File;
import org.w3c.dom.Document;

public class SchemaTest {
public static void main (String args[]) {
File docFile = new File("memory.xml");
try {
DOMParser parser = new DOMParser();
parser.setFeature("http://xml.org/sax/features/validation", true);
parser.setProperty(
"http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",
"memory.xsd");
ErrorChecker errors = new ErrorChecker();
parser.setErrorHandler(errors);
parser.parse("memory.xml");
} catch (Exception e) {
System.out.print("Problem parsing the file.");
}
}
}
Ответ 3

Мы создаем наш проект с использованием ant, поэтому можем использовать задачу schemavalidate для проверки наших конфигурационных файлов:

<schemavalidate> 
<fileset dir="${configdir}" includes="**/*.xml" />
</schemavalidate>

Теперь непослушные конфигурационные файлы не смогут выполнить нашу сборку!

http://ant.apache.org/manual/Tasks/schemavalidate.html

Ответ 4

Поскольку это популярный вопрос, я укажу, что java также может проверять на соответствие "ссылочным" xsd-файлам, например, если сам XML-файл указывает XSD-файлы в заголовке, используя xsi:schemaLocation или xsi:noNamespaceSchemaLocation (или xsi для определенных пространств имен) например:

<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, все в порядке. Но иногда удобно иметь собственный распознаватель...

Из javadocs: "Если вы создаете схему без указания URL, файла или источника, то язык Java создает схему, которая ищет в проверяемом документе схему, которую он должен использовать. Например:"

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();

и это работает для нескольких пространств имен и т.д.
Проблема с этим подходом заключается в том, что xmlsns:xsi вероятно, это сетевое местоположение, поэтому по умолчанию оно будет выходить и попадать в сеть при каждой проверке, что не всегда оптимально.

Вот пример, который проверяет XML-файл на соответствие любым ссылкам XSD на it (даже если для этого приходится извлекать их из сети):

  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 catalog". 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://javalang.ru/a/2342859/32453
}
});
validator.validate(xmlFile);

Смотрите также Здесь другое руководство.

Я полагаю, что по умолчанию используется синтаксический анализ DOM, вы можете сделать что-то подобное с SAX parser, который также проверяет saxReader.setEntityResolver(your_resolver_here);

java xml