Вопрос:

Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?

java xml validation xsd

243342 просмотра

12 ответа

1507 Репутация автора

Я генерирую некоторые xml-файлы, которые должны соответствовать xsd-файлу, который мне дали. Какой лучший способ убедиться, что они соответствуют?

Автор: Jeff Источник Размещён: 19.08.2008 04:59

Ответы (12)


25 плюса

26104 Репутация автора

Вот как это сделать с помощью 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.");
     }
  }
}
Автор: SCdF Размещён: 19.08.2008 05:10

0 плюса

13259 Репутация автора

Вы ищете инструмент или библиотеку?

Что касается библиотек, то фактически стандартом де-факто является Xerces2, который имеет версии C ++ и Java .

Будьте предупреждены, хотя, это решение для тяжелого веса. Но опять же, проверка XML по файлам XSD является довольно сложной проблемой.

Что касается инструмента, который сделает это за вас, то XMLFox кажется неплохим бесплатным решением, но я не могу сказать наверняка, что не использовал его лично.

Автор: Adam Размещён: 19.08.2008 05:11

312 плюса

94463 Репутация автора

Решение

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

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которая определяет XSD. Приведенный выше код проверяет дескриптор развертывания WAR по URL, http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsdно вы также можете легко проверить по локальному файлу.

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

Автор: McDowell Размещён: 19.08.2008 12:21

-2 плюса

182 Репутация автора

Мне пришлось проверять XML на XSD всего один раз, поэтому я попробовал XMLFox. Я нашел это очень запутанным и странным. Похоже, что справочные инструкции не соответствуют интерфейсу.

В итоге я использовал LiquidXML Studio 2008 (v6), который был намного проще в использовании и более знакомым (пользовательский интерфейс очень похож на Visual Basic 2008 Express, который я часто использую). Недостаток: возможность проверки отсутствует в бесплатной версии, поэтому мне пришлось использовать 30-дневную пробную версию.

Автор: KnomDeGuerre Размещён: 01.10.2008 05:35

2 плюса

1321 Репутация автора

Если вы генерируете XML-файлы программно, вы можете обратиться к библиотеке XMLBeans . Используя инструмент командной строки, XMLBeans будет автоматически генерировать и упаковывать набор объектов Java на основе XSD. Затем вы можете использовать эти объекты для создания XML-документа на основе этой схемы.

Он имеет встроенную поддержку проверки схемы и может преобразовывать объекты Java в документ XML и наоборот.

Castor и JAXB - это другие библиотеки Java, которые служат аналогично XMLBeans.

Автор: Todd Размещён: 28.01.2009 06:06

3 плюса

81923 Репутация автора

Еще один ответ: так как вы сказали, что вам нужно проверять файлы, которые вы генерируете (записываете), вы можете проверить контент во время записи, вместо того, чтобы сначала писать, а затем читать обратно для проверки. Вероятно, вы можете сделать это с помощью JDK API для проверки XML, если вы используете средство записи на основе SAX: если это так, просто создайте ссылку в валидаторе, вызвав Validator.validate (source, result), где источник исходит от вашего средства записи, а результат где выход должен идти.

В качестве альтернативы, если вы используете Stax для записи содержимого (или библиотеку, которая использует или может использовать stax), Woodstox также может напрямую поддерживать проверку при использовании XMLStreamWriter. Вот запись в блоге, показывающая, как это делается:

Автор: StaxMan Размещён: 27.03.2009 04:25

20 плюса

5579 Репутация автора

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

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

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

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

Автор: chickeninabiscuit Размещён: 14.07.2011 08:01

3 плюса

2293 Репутация автора

Если у вас есть Linux-машина, вы можете использовать бесплатный инструмент командной строки SAXCount. Я нашел это очень полезным.

SAXCount -f -s -n my.xml

Это проверяет против dtd и xsd. 5 с для файла 50 МБ.

В Debian Squeeze он находится в пакете "libxerces-c-samples".

Определение dtd и xsd должно быть в xml! Вы не можете настроить их отдельно.

Автор: jens Размещён: 22.03.2012 05:01

5 плюса

16027 Репутация автора

Используя Java 7, вы можете следовать документации, представленной в описании пакета .

// parse an XML document into a DOM tree
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = parser.parse(new File("instance.xml"));

// create a SchemaFactory capable of understanding WXS schemas
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

// load a WXS schema, represented by a Schema instance
Source schemaFile = new StreamSource(new File("mySchema.xsd"));
Schema schema = factory.newSchema(schemaFile);

// create a Validator instance, which can be used to validate an instance document
Validator validator = schema.newValidator();

// validate the DOM tree
try {
    validator.validate(new DOMSource(document));
} catch (SAXException e) {
    // instance document is invalid!
}
Автор: Paulo Fidalgo Размещён: 13.05.2013 09:40

11 плюса

34148 Репутация автора

Так как это популярный вопрос, я укажу, что 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">
  ...

«Если вы создаете схему без указания 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);

Смотрите также здесь для другого учебника.

Автор: rogerdpack Размещён: 19.12.2016 02:57

0 плюса

503 Репутация автора

С JAXB вы можете использовать код ниже:

    @Test
public void testCheckXmlIsValidAgainstSchema() {
    logger.info("Validating an XML file against the latest schema...");

    MyValidationEventCollector vec = new MyValidationEventCollector();

    validateXmlAgainstSchema(vec, inputXmlFileName, inputXmlSchemaName, inputXmlRootClass);

    assertThat(vec.getValidationErrors().isEmpty(), is(expectedValidationResult));
}

private void validateXmlAgainstSchema(final MyValidationEventCollector vec, final String xmlFileName, final String xsdSchemaName, final Class<?> rootClass) {
    try (InputStream xmlFileIs = Thread.currentThread().getContextClassLoader().getResourceAsStream(xmlFileName);) {
        final JAXBContext jContext = JAXBContext.newInstance(rootClass);
        // Unmarshal the data from InputStream
        final Unmarshaller unmarshaller = jContext.createUnmarshaller();

        final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final InputStream schemaAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xsdSchemaName);
        unmarshaller.setSchema(sf.newSchema(new StreamSource(schemaAsStream)));

        unmarshaller.setEventHandler(vec);

        unmarshaller.unmarshal(new StreamSource(xmlFileIs), rootClass).getValue(); // The Document class is the root object in the XML file you want to validate

        for (String validationError : vec.getValidationErrors()) {
            logger.trace(validationError);
        }
    } catch (final Exception e) {
        logger.error("The validation of the XML file " + xmlFileName + " failed: ", e);
    }
}

class MyValidationEventCollector implements ValidationEventHandler {
    private final List<String> validationErrors;

    public MyValidationEventCollector() {
        validationErrors = new ArrayList<>();
    }

    public List<String> getValidationErrors() {
        return Collections.unmodifiableList(validationErrors);
    }

    @Override
    public boolean handleEvent(final ValidationEvent event) {
        String pattern = "line {0}, column {1}, error message {2}";
        String errorMessage = MessageFormat.format(pattern, event.getLocator().getLineNumber(), event.getLocator().getColumnNumber(),
                event.getMessage());
        if (event.getSeverity() == ValidationEvent.FATAL_ERROR) {
            validationErrors.add(errorMessage);
        }
        return true; // you collect the validation errors in a List and handle them later
    }
}
Автор: razvanone Размещён: 27.11.2017 03:25

0 плюса

2084 Репутация автора

Проверка по сетевым схемам

Source xmlFile = new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("your.xml"));
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(Thread.currentThread().getContextClassLoader().getResource("your.xsd"));
Validator validator = schema.newValidator();
validator.validate(xmlFile);

Проверка по локальным схемам

Автономная проверка XML с помощью Java

Автор: jschnasse Размещён: 04.10.2018 11:36
32x32