- Validate XML against XSD Schema using Java
- Project structure
- XSD Schema
- XSD Validator
- Getting the line and column number
- Output
- References
- Валидация XML с помощью XSD, JAXB и Spring Framework
- 1. Исходные файлы и схемы
- 2. Конфигурация Spring
- 3. Преобразование XML-Java
- 4. Демонстрация работы программы
- How to validate XML against XSD in Java
- Validate XML against XSD
Validate XML against XSD Schema using Java
In this example we will Validate XML against XSD Schema. We use the javax.xml.validation.Validator to check the XML document against the XSD schema. Be careful because the validator is not thread safe. It is the responsibility of the application to make the code thread safe. The validation is successful when the validator.validate() method does not throw an exception.
Project structure
+--src | +--main | +--java | +--com | +--memorynotfound | |--ValidateXmlXsd.java | +--resources | |--schema.xsd pom.xml
XSD Schema
XSD Validator
To validate XML against XSD schema we need to create a schema and a validator. Next we validate the XML against the XSD schema. The validation is successful if the validator.validate() method does not throw an exception.
Warning: A validator is NOT thread save. It is the responsibility of the application to make sure that one Validator object is not used from more than one thread at any given time.
package com.memorynotfound.xml.xsd; import org.xml.sax.SAXException; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import java.io.IOException; import java.io.StringReader; public class ValidateXmlXsd < public static String xml = "\n" + "JAX-B\n" + " Validate XML against XSD Schema \n" + " "; public static void main(String. args) < try < System.out.println("Validate XML against XSD Schema"); SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = factory.newSchema(ValidateXmlXsd.class.getResource("/schema.xsd")); Validator validator = schema.newValidator(); validator.validate(new StreamSource(new StringReader(xml))); System.out.println("Validation is successful"); >catch (IOException e) < // handle exception while reading source >catch (SAXException e) < System.out.println("Error when validate XML against XSD Schema"); System.out.println("Message: " + e.getMessage()); >> >
Getting the line and column number
If you need to display the line or column number, read this tutorial.
Output
Validate XML against XSD Schema Error when validate XML against XSD Schema Message: cvc-datatype-valid.1.2.1: '1-ID' is not a valid value for 'integer'.
References
Валидация XML с помощью XSD, JAXB и Spring Framework
Здравствуйте! В этой статье я хочу описать программу валидации XML с помощью Spring Framework. Наиболее очевидная область применения такой валидации — это программирование web-сервисов.
Валидация производится через преобразование XML-Java (unmarshalling) по соответствующей XSD-схеме. XML-файл считается прошедшим проверку, если преобразование XML в объект Java прошло успешно.
Проект компилируется в jar файл и запускается в командной строке. Для красоты прикручен Apache ANSI Printer, в котором можно задавать шрифт, цвет и выделение текста в cmd.
Исходный код доступен в GitHub по ссылке XmlProcessor.
1. Исходные файлы и схемы
В качестве входных данных определим 2 XML файла Address.xml и Client.xml.
V001.000.00 50 7 Sadovaya SPB Russia 123456
Далее определим XSD-схемы XmlValidator.xsd, ComplexTypes.xsd и SimpleTypes.xsd с
описанием контейнера CombinedType и объектов типа Address и Client:
XSD structure XML definition
The version Address type Client type Apartment number House number Street name City name Country name Postal index The id The name
V000.000.00 .7.9"/> Int, 10 max String, 50 max Int, 4 max Int, 3 max String, 40 max City, 40 max Country, 30 max Int, 10 max
Обратите внимание на элемент в CombinedType схемы ComplexTypes.xsd. Он означает, что xml-файл должен содержать либо один элемент типа Address, либо один или несколько элементов типа Client.
2. Конфигурация Spring
В файле spring-config.xml находится описание используемых в проекте бинов Printer,
FileReader, Marshaller, XMLService. Помимо указанных бинов, определен фильтр расширений
FileNameExtensionFilter, чтобы рассматривать только xml-файлы.
xml
com.xmlprocessor.types.CombinedType
xmlvalidator.xsd complextypes.xsd simpletypes.xsd
3. Преобразование XML-Java
В точке входа приложения XmlProcessorDrv сначала считываем и проверяем аргументы
командной строки, затем через вызов методов класса Compositor создаем бины printer,
fileReader и xmlService. Далее считываем xml-файлы и выполняем валидацию файлов в
директории, указанной в CLI_OPTION_DIRECTORY.
Самое интересное происходит при вызове
xmlService.validate(xmlFiles)
package com.xmlprocessor.main; import java.io.File; import java.util.List; import com.xmlprocessor.config.Compositor; import com.xmlprocessor.service.api.PrinterInt; import com.xmlprocessor.service.api.XmlServiceInt; import com.xmlprocessor.util.CommandLineArgs; public class XmlProcessorDrv < /** Name of the program */ private static final String PROG_NAME = XmlProcessorDrv.class.getSimpleName(); /** Version of the Program */ private static final String PROG_VERSION = "1.0 (XmlProcessor v1.000)"; /** Exit Status for OK. */ private static final int EXIT_STATUS_OK = 0; /** Exit Status for not OK. */ private static final int EXIT_STATUS_NOT_OK = -1; /** * Main entry point. * Evaluates command line args and validates provided xml files * * @param args * Command line arguments */ public static void main(String[] args) < // execution status int exitStatus; // get printer object PrinterInt printer = Compositor.getPrinter(); // read command line args CommandLineArgs cmdLineArgs = new CommandLineArgs(args); // Show version if (cmdLineArgs.hasOption(CommandLineArgs.CLI_OPTION_VERSION)) < printer.printf("%s v%s\n", PROG_NAME, PROG_VERSION); >// Show help if (cmdLineArgs.hasOption(CommandLineArgs.CLI_OPTION_HELP)) < cmdLineArgs.printHelp(PROG_NAME); >// Check if the directory name is passed in args if (!cmdLineArgs.hasOption(CommandLineArgs.CLI_OPTION_DIRECTORY)) < cmdLineArgs.printHelp(PROG_NAME); return; >String dir = cmdLineArgs.getOptionValue(CommandLineArgs.CLI_OPTION_DIRECTORY); printer.printf("\n%s %s","Folder with XML files: ", dir); List xmlFiles; XmlServiceInt xmlService = Compositor.getXmlService(); try < xmlFiles = Compositor.getFileReader().readFiles(dir); printer.bold("\n\nStart validating XML files:\n"); xmlService.validate(xmlFiles); exitStatus = EXIT_STATUS_OK; >catch (Exception ex) < printer.errorln("\n" + ex.getMessage()); exitStatus = EXIT_STATUS_NOT_OK; >System.exit(exitStatus); > // main >
Код метода validate представлен ниже.
. /** */ public void validate(List xmlFiles) throws Exception < int fileCount = xmlFiles.size(); File currentFile; FileInputStream fileInputStream = null; Source xmlFileSource; CombinedType combinedType; AddressType addressType; for (int count = 0; count < fileCount; count++) < currentFile = xmlFiles.get(count); printer.boldln("Current file: ").println(currentFile.getPath()); try < fileInputStream = new FileInputStream(currentFile); xmlSource = new StreamSource(fileInputStream); combinedType = (CombinedType)unmarshaller.unmarshal(xmlSource); printer.boldln("Xml file [" + currentFile.getName() + "] validation success!\n"); printer.boldln("Version: ").println(combinedType.getVersion()); addressType = combinedType.getAddress(); if (addressType != null) < printer.boldln("Address: ").println(addressType.toString()); >else if (combinedType.getClients() != null) < int i=0; for (ClientType client : combinedType.getClients()) < printer.boldln("Client").println("[" + ++i + "]" + client.toString()); >> > catch(Exception e) < printer.fatalln("Xml file [" + currentFile.getName() + "] validation error: \n" + e.getMessage()); >finally < if (fileInputStream != null) < fileInputStream.close(); >> > printer.boldln("Validating complete."); >
Ключевое преобразование XML-Java или unmarshalling происходит в строке
combinedType = (CombinedType)unmarshaller.unmarshal(xmlSource);
Как уже упоминалось, если удалось из XML получить java-объект типа CombinedType, то
XML признается корректным.
Unmarshaller-у должен быть заранее известен конечный объект преобразования. Для
этого с помощью JAXB создадим файлы AddressType.java, ClientType.java, CombinedType.java
В IDE Eclipse: правый клик по XSD -> Generate -> JAXB Classes…
package com.xmlprocessor.types; import java.math.BigInteger; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * Java class for AddressType complex type.
*/ @SuppressWarnings("restriction") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AddressType", propOrder = < "apartment", "street", "house", "city", "country", "index" >) public class AddressType < @XmlElement(name = "Apartment", required = true) protected Integer apartment; @XmlElement(name = "House", required = true) protected BigInteger house; @XmlElement(name = "Street", required = true) protected String street; @XmlElement(name = "City", required = true) protected String city; @XmlElement(name = "Country", required = true) protected String country; @XmlElement(name = "Index") protected BigInteger index; public Integer getApartment() < return apartment; >public void setApartment(Integer value) < this.apartment = value; >public String getStreet() < return street; >public void setStreet(String value) < this.street = value; >public BigInteger getHouse() < return house; >public void setHouse(BigInteger value) < this.house = value; >public String getCity() < return city; >public void setCity(String value) < this.city = value; >public String getCountry() < return country; >public void setCountry(String value) < this.country = value; >public BigInteger getIndex() < return index; >public void setIndex(BigInteger value) < this.index = value; >public boolean isSetIndex() < return (this.index!= null); >@Override public String toString() < StringBuilder sb = new StringBuilder(); sb.append("\nApartment#: " + apartment); sb.append("\nHouse#: " + house); sb.append("\nStreet: " + street); sb.append("\nCity: " + city); sb.append("\nCountry: " + country); if (this.isSetIndex()) < sb.append("\nIndex: " + index); >return sb.toString(); > >
package com.xmlprocessor.types; import java.math.BigInteger; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @SuppressWarnings("restriction") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "ClientType", namespace = "http://www.tempuri.org/complextypes", propOrder = < "id", "name" >) public class ClientType < @XmlElement(name = "Id", required = true) protected BigInteger id; @XmlElement(name = "Name", required = true) protected String name; public BigInteger getId() < return id; >public void setId(BigInteger value) < this.id = value; >public String getName() < return name; >public void setName(String value) < this.name = value; >@Override public String toString() < StringBuilder sb = new StringBuilder(); sb.append("\nId: " + id); sb.append("\nName: " + name); return sb.toString(); >>
package com.xmlprocessor.types; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * Java class for CombinedType complex type. */ @SuppressWarnings("restriction") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "CombinedType", propOrder = < "version", "clients", "address" >) @XmlRootElement(name = "Combined", namespace = "http://www.tempuri.org/types") public class CombinedType < @XmlElement(name = "Version", required = true) protected String version; @XmlElement(name = "Client") protected Listclients; @XmlElement(name = "Address") protected AddressType address; public String getVersion() < return version; >public void setVersion(String value) < this.version = value; >public List getClients() < if (clients == null) < clients = new ArrayList(); > return this.clients; > public AddressType getAddress() < return address; >public void setAddress(AddressType value) < this.address = value; >>
4. Демонстрация работы программы
В проект включен файл Readme с описанием доступных опций и аргументов командной
строки:
XmlProcessor v1.0 Usage: java -jar XmlProcessorDrv [-d ] [-h] [-v] -h,--help Display this help -v Version of the program -d Folder with XML files to be validated Example: java -jar xmlProcessor.jar --help -v -d "C:\\XmlSample"
Для запуска проекта из cmd скомпилируем jar, вызвав Maven build package на pom.xml, и в
cmd введем вышеописанную команду
java -jar xmlProcessor.jar -h -v -d «C:\XmlSample»
Директория C:\XmlSample должна содержать один или несколько файлов вида Address.xml и
Client.xml. Файлы с расширением не xml будут проигнорированы.
Пример корректной работы программы:
Программа выдаст ошибку, если длина поля превышает установленный в SimpleTypes.xsd предел, имеется опечатка в имени узла, итд. Для примера допустим, что первый элемент адреса написан как AApartment:
V001.000.00 50 7 Sadovaya Saint Petersburg Russia 123456
В этом случае программа выдаст ошибку:
How to validate XML against XSD in Java
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
Java XML Validation API can be used to validate XML against XSD in java program. javax.xml.validation.Validator class is used in this program to validate xml against xsd in java.
Validate XML against XSD
Here are the sample XSD and XML files used. Employee.xsd
Notice that above XSD contains two root element and namespace also, I have created two sample XML file from XSD using Eclipse. EmployeeRequest.xml
Pankaj 29 Java Developer Male
Here is the program that is used to validate all three XML files against the XSD. The validateXMLSchema method takes XSD and XML file as argument and return true if validation is successful or else returns false. XMLValidation.java
package com.journaldev.xml; import java.io.File; import java.io.IOException; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import org.xml.sax.SAXException; public class XMLValidation < public static void main(String[] args) < System.out.println("EmployeeRequest.xml validates against Employee.xsd? "+validateXMLSchema("Employee.xsd", "EmployeeRequest.xml")); System.out.println("EmployeeResponse.xml validates against Employee.xsd? "+validateXMLSchema("Employee.xsd", "EmployeeResponse.xml")); System.out.println("employee.xml validates against Employee.xsd? "+validateXMLSchema("Employee.xsd", "employee.xml")); >public static boolean validateXMLSchema(String xsdPath, String xmlPath) < try < SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = factory.newSchema(new File(xsdPath)); Validator validator = schema.newValidator(); validator.validate(new StreamSource(new File(xmlPath))); >catch (IOException | SAXException e) < System.out.println("Exception: "+e.getMessage()); return false; >return true; > >
EmployeeRequest.xml validates against Employee.xsd? true EmployeeResponse.xml validates against Employee.xsd? true Exception: cvc-elt.1: Cannot find the declaration of element 'Employee'. employee.xml validates against Employee.xsd? false
The benefit of using Java XML validation API is that we don’t need to parse the file and there is no third party APIs used.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases. Learn more about us