XML Validation
XML Syntax Errors
vscode-xml provides the capability to report XML syntax errors when the XML is not valid:
For many of the errors, you can use a Quick Fix (code action) to help you fix the XML:
Validation with a given grammar
You can validate your XML with a grammar (XSD, DTD). In order to do so, you must associate your XML document with a grammar. Once you have done this, you will benefit from:
- XML
validationbased on the grammar. - XML
completionbased on the grammar. - XML
hoverbased on the grammar in order to show the documentation.
If the xml.symbols.showReferencedGrammars setting is enabled, the method used to associate each grammar is listed in the document symbols.
Please see the Show Referenced Grammars documentation for more information.
Validation with XSD grammar
In the following sections, we would like to validate the XML foo.xml file:
with the XSD foo.xsd file (in the same folder as foo.xml) :
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="foo"> <xs:complexType> <xs:sequence> <xs:element name="bar" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
in order to benefit from validation, completion, and hover based on the XSD:
To associate your XML document with an XSD grammar, you can use several strategies:
- xsi:noNamespaceSchemaLocation
- xsi:schemaLocation
- xml-model with XSD processing instruction
- XML catalog with XSD
- XML file association
If you have an XML without an XSD, you can generate the XSD with a Quick Fix (code action):
The Quick Fix will generate the XSD file and associate the XML with the XSD using the chosen strategy.
xsi:noNamespaceSchemaLocation
To bind the XML file foo.xml with the XSD file foo.xsd, you can use the xsi:noNamespaceSchemaLocation strategy like this:
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="foo.xsd"> <bar /> </foo>
xsi:schemaLocation
The xsi:schemaLocation strategy is used when the XML document defines a namespace and the elements in the document are associated with that namespace:
<foo xmlns="http://foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://foo foo.xsd"> <bar /> </foo>
In this case, the corresponding XSD file defines targetNamespace="http://foo" in the root element of the XSD:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://foo"> <xs:element name="foo"> <xs:complexType> <xs:sequence> <xs:element name="bar" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
xml-model with XSD
To bind the XML file foo.xml to the XSD file foo.xsd, you can use xml-model processing instruction strategy like this:
<?xml-model href="foo.xsd" ?> <foo> <bar /> </foo>
XML catalog with XSD
Using an XML catalog can be helpful when you wish to use elements from a namespace but don’t want to set the real path of the XSD file for each XML document.
In other words you want to write this XML file:
<foo xmlns="http://foo" > <bar /> </foo>
and validate it with the foo.xsd XSD file:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://foo"> <xs:element name="foo"> <xs:complexType> <xs:sequence> <xs:element name="bar" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
To do this, you need to write an XML catalog, and an entry for the XSD. In this example, we’ll name the catalog catalog.xml. The catalog looks like this:
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"> <uri name="http://foo" uri="./foo.xsd" /> </catalog>
You must register your catalog.xml in the vscode settings.json like this:
"xml.catalogs": [ "catalog.xml" ]
You can also register the catalog using its absolute path:
| Windows | MacOS | Linux |
|---|---|---|
C:\Users\path\to\catalog.xml |
/Users/path/to/catalog.xml |
/home/path/to/catalog.xml |
Please note that you can declare your catalog path with file:/// if you need it.
Another useful option are the rewrite rules. Given the same xml as before but now with xmlns="http://foo.web/foo/types.xsd" can be adjusted to use a local types.xsd as follows:
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"> <rewriteURI uriStartString="http://foo.web/foo/" rewritePrefix="./" /> </catalog>
XML file association with XSD
You can use the XML file association strategy to bind the XML file foo.xml with the XSD file foo.xsd by adding the following into your vscode settings.json:
"xml.fileAssociations": [ { "pattern": "foo.xml", "systemId": "foo.xsd" } ]
Please note that you can use wildcards in the pattern (ex: foo*.xml):
"xml.fileAssociations": [ { "pattern": "foo*.xml", "systemId": "foo.xsd" } ]
In this case, all XML files that start with foo and end with .xml will be associated with the XSD (foo1.xml, foo2.xml, etc)
You can also use the following three variables in either the pattern or systemId:
| Variable | Meaning |
|---|---|
| ${workspaceFolder} | The absolute path to root folder of the workspace that is currently open |
| ${fileDirname} | The absolute path to the folder of the file that is currently opened |
| ${fileBasenameNoExtension} | The current opened file’s basename with no file extension |
If one of the variables for an association can’t be expanded (eg. because vscode is opened in rootless mode),
the association is ignored.
This feature is specific to the VSCode client.
Please note that if the XSD defines a targetNamespace="http://foo" like the following foo.xsd XSD file:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://foo"> <xs:element name="foo"> <xs:complexType> <xs:sequence> <xs:element name="bar" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
the following XML file association:
"xml.fileAssociations": [ { "pattern": "foo*.xml", "systemId": "foo.xsd" } ]
will work with the following foo.xml XML file only if it declares the http://foo namespace:
<foo xmlns="http://foo" > <bar /> </foo>
Validation with DTD grammar
To associate your XML with a DTD grammar you can use several strategies:
- DOCTYPE
- xml-model with DTD processing instruction
- XML catalog with DTD
- XML file association with DTD
In the following sections we would like to validate the XML foo.xml file:
with the DTD foo.dtd file:
<!ELEMENT foo (bar)> <!ELEMENT bar EMPTY>
Please note: this DTD file can be generated with the same Quick Fix which generates the XSD.
DOCTYPE
To bind the XML file foo.xml with the DTD file foo.dtd, you can use the DOCTYPE strategy like this:
<!DOCTYPE foo SYSTEM "foo.dtd"> <foo> <bar /> </foo>
xml-model with DTD
To bind XML file foo.xml with the DTD file foo.dtd, you can use xml-model processing instruction strategy like this:
<?xml-model href="foo.dtd" ?> <foo> <bar /> </foo>
XML catalog with DTD
Using an XML catalog can be helpful when you wish to associate to a DTD using a PUBLIC declaration, but don’t want to set the real path of the DTD file (SYSTEM).
In other words you want to write this XML file:
<!DOCTYPE foo PUBLIC "-//FOO" "XXXXXXXXXXXXXXX.dtd"> <foo> <bar /> </foo>
and validate it with this foo.dtd DTD file:
<!ELEMENT foo (bar)> <!ELEMENT bar EMPTY>
The declared XXXXXXXXXXXXXXX.dtd in the DOCTYPE is a file which doesn’t exist. The foo.dtd will be retrieved using the PUBLIC -//FOO.
To do this, you need to write an XML catalog, and an entry for the DTD. In this example, we’ll name the catalog catalog.xml. The catalog looks like this:
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"> <public publicId="-//FOO" uri="./foo.dtd" /> </catalog>
and in vscode settings.json you must register your catalog.xml like this:
"xml.catalogs": [ "catalog.xml" ]
You can also register the catalog using its absolute path:
| Windows | MacOS | Linux |
|---|---|---|
C:\Users\path\to\catalog.xml |
/Users/path/to/catalog.xml |
/home/path/to/catalog.xml |
XML file association with DTD
You can use the XML file association strategy to bind the XML file foo.xml with the DTD file foo.dtd by adding the following into your vscode settings.json:
"xml.fileAssociations": [ { "pattern": "foo.xml", "systemId": "foo.dtd" } ]
Please note that you can use wildcards in the pattern (ex: foo*.xml):
"xml.fileAssociations": [ { "pattern": "foo*.xml", "systemId": "foo.dtd" } ]
In this case, all XML files that start with foo and end with .xml will be associated with the DTD (foo1.xml, foo2.xml, etc)
You can also use the following three variables in either the pattern or systemId:
| Variable | Meaning |
|---|---|
| ${workspaceFolder} | The absolute path to root folder of the workspace that is currently open |
| ${fileDirname} | The absolute path to the folder of the file that is currently opened |
| ${fileBasenameNoExtension} | The current opened file’s basename with no file extension |
If one of the variables for an association can’t be expanded (eg. because vscode is opened in rootless mode),
the association is ignored.
This feature is specific to the VSCode client.
Validation with RelaxNG grammar
See RelaxNG features
Other Validation Settings
Disallow Doc Type Declarations
If xml.validation.disallowDocTypeDeclaration is set to true (default is false), all Doc Type Declarations (DTD) will be marked as errors. The DOCTYPE is marked as an error regardless if the doctype is an internally declared or a reference to an external DTD. Standalone .dtd files are not marked as an error.
Here are some examples of files with xml.validation.disallowDocTypeDeclaration set to true:
Resolve External Entities
If xml.validation.resolveExternalEntities is set to true (default is false), then the value of external entities are resolved for validation. This means that the file referenced in the external entity declaration will be downloaded. The default is false due to the xml external entity attack.
In an untrusted workspace, this feature is disabled.
Demonstration of the different behaviour:
xml.validation.namespaces.enabled
The xml.validation.namespaces.enabled gives the capability to enable / disable the namespaces (prefix) validation. It can be configured with 3 values:
always: enable schema based validation.never: disable schema based validation.onNamespaceEncountered: enable namespaces validation only when the root element declares an xmlns namespace.
To understand the onNamespaceEncountered settings value, lets go through an example:
Create the XML foo.xml file:
In always you will have error, in onNamespaceEncountered you will have none error.
Declares a namespaces in the foo root element:
<foo xmlns="http:foo" > <p:bar /> </foo>
In onNamespaceEncountered you will see a prefix error.
xml.validation.schema.enabled
The xml.validation.schema.enabled gives the capability to enable / disable the validation based on XSD. It can be configured with 3 values:
always: enable schema based validation.never: disable schema based validation.onValidSchema: enable schema based validation only when the declared xsi:schemaLocation hint or xsi:noNamespaceSchemaLocation is valid for the root element.
To understand the onValidSchema settings value, lets go through an example:
Create the XML foo.xml file:
<foo xmlns="http://foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://foo foo.xsd"> <bar /> <BAD_ELEMENT /> </foo>
Create the XSD foo.xsd file (in the same folder as foo.xml) :
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="foo"> <xs:complexType> <xs:sequence> <xs:element name="bar" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
In the XML file, the BAD_ELEMENT is higlighted as an error. Update the xsi:schemaLocation with bad namespace hint
<foo> ... xsi:schemaLocation=" http://bad-foo foo.xsd"> ... </foo>
In always you will have error, in onValidSchema you will have none error.
Now, update the xsi:schemaLocation with bad location hint
<foo> ... xsi:schemaLocation=" http://foo bad-foo.xsd"> ... </foo>
In always you will have error, in onValidSchema you will have none error.
xml.validation.filters
XML validation filter gives you the capability to define validation rules for files matching a given pattern. For instance if you wish to disable validation for all files which have the *.myxml file extension, you must declare this filter in the settings.json:
"xml.validation.filters": [ // Declaration of validation filter to disable validation for all *.myxml files. { "pattern": "**.myxml", "enabled": false } ]
You can use other validation settings (enabled, noGrammar, etc). For instance if you wish to remove the warning no grammar for all files which have the *.myxml file extension, you must declare this filter in the settings.json:
"xml.validation.filters": [ // Declaration of validation filter to disable validation for all *.myxml files. { "pattern": "**.myxml", "noGrammar": "ignore" } ]
By default, vscode-xml uses this default validation filter:
"xml.validation.filters": [ // Ignore no grammar hint and disable XSD validation for *.exsd Eclipse files. { "pattern": "**.exsd", "noGrammar": "ignore", "schema": { "enabled": "never" } }, // Ignore no grammar hint for Eclipse files like .project { "pattern": "**{.project,.classpath,plugin.xml,feature.xml,category.xml,.target,.product}", "noGrammar": "ignore" } ]
xml.validation.xInclude.enabled
The xml.validation.xInclude.enabled gives the capability to enable / disable the validation for XInclude. Defaults to false.
See XInclude features
I need to validate a XML file against a schema. The XML file is being generated in code and before I save it I need to validate it to be correct.
I have stripped the problem down to its barest elements but am having an issue.
XML:
<?xml version="1.0" encoding="utf-16"?>
<MRIDSupportingData xmlns="urn:GenericLabData">
<MRIDNumber>MRIDDemo</MRIDNumber>
<CrewMemberIdentifier>1234</CrewMemberIdentifier>
<PrescribedTestDate>1/1/2005</PrescribedTestDate>
</MRIDSupportingData>
Schema:
<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns="urn:GenericLabData" targetNamespace="urn:GenericLabData"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="MRIDSupportingData">
<xs:complexType>
<xs:sequence>
<xs:element name="MRIDNumber" type="xs:string" />
<xs:element minOccurs="1" name="CrewMemberIdentifier" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
ValidationCode: (This code is from a simple app I wrote to test the validation logic. The XML and XSD files are stored on disk and are being read from there. In the actual app, the XML file would be in memory already as an XmlDocument object and the XSD would be read from an internal webserver.)
private void Validate()
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(OnValidate);
XmlSchemaSet schemas = new XmlSchemaSet();
settings.Schemas = schemas;
try
{
schemas.Add(null, schemaPathTextBox.Text);
using (XmlReader reader = XmlReader.Create(xmlDocumentPathTextBox.Text, settings))
{
validateText.AppendLine("Validating...");
while (reader.Read()) ;
validateText.AppendLine("Finished Validating");
textBox1.Text = validateText.ToString();
}
}
catch (Exception ex)
{
textBox1.Text = ex.ToString();
}
}
StringBuilder validateText = new StringBuilder();
private void OnValidate(object sender, ValidationEventArgs e)
{
switch (e.Severity)
{
case XmlSeverityType.Error:
validateText.AppendLine(string.Format("Error: {0}", e.Message));
break;
case XmlSeverityType.Warning:
validateText.AppendLine(string.Format("Warning {0}", e.Message));
break;
}
}
When running the above code with the XML and XSD files defined above I get this output:
Validating…
Error: The element ‘MRIDSupportingData’ in namespace ‘urn:GenericLabData’ has invalid child element ‘MRIDNumber’ in namespace ‘urn:GenericLabData’. List of possible elements expected: ‘MRIDNumber’.
Finished Validating
What am I missing? As far as I can tell, MRIDNumber is MRIDNumber so why the error?
The actual XML file is much larger as well as the XSD, but it fails at the very beginning, so I have reduced the problem to almost nothing.
Any assistance on this would be great.
Thank you,
Keith
BTW, These files do work:
XML:
<?xml version='1.0'?>
<bookstore xmlns="urn:bookstore-schema">
<book genre="novel">
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
</bookstore>
Schema:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="urn:bookstore-schema"
elementFormDefault="qualified"
targetNamespace="urn:bookstore-schema">
<xsd:element name="bookstore">
<xsd:complexType>
<xsd:sequence >
<xsd:element name="book" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence >
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author">
<xsd:complexType>
<xsd:sequence >
<xsd:element name="first-name" type="xsd:string"/>
<xsd:element name="last-name" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="price" type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="genre" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Learn to validate XML against schema (xsd) and then unmarshalling XML to Java object. Also learn to check validation errors during xml schema validation if validation fails.
Read More: How to generate schema from JAXB classes
1. Convert XML to Java Object after XSD Validation
We have already seen the example to read XML file to Java object. Let’s modify that example to now validate the XML against XSD before populating the Employee object.
package com.howtodoinjava.demo;
import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
import com.howtodoinjava.demo.model.Employee;
public class JaxbExample
{
public static void main(String[] args)
{
String xmlFile = "employee.xml";
String xsdFile = "employee.xsd";
jaxbXmlFileToObject(xmlFile, xsdFile);
}
private static void jaxbXmlFileToObject(String xmlFile, String xsdFile) {
JAXBContext jaxbContext;
try
{
//Get JAXBContext
jaxbContext = JAXBContext.newInstance(Employee.class);
//Create Unmarshaller
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
//Setup schema validator
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema employeeSchema = sf.newSchema(new File(xsdFile));
jaxbUnmarshaller.setSchema(employeeSchema);
//Unmarshal xml file
Employee employee = (Employee) jaxbUnmarshaller.unmarshal(new File(xmlFile));
System.out.println(employee);
}
catch (JAXBException | SAXException e)
{
e.printStackTrace();
}
}
}
Program output.
Employee [id=1, firstName=Lokesh, lastName=Gupta, department=Department [id=101, name=IT]]
Where the content of employee.xml and employee.xsd is given below.
<employees> <employee id="101"> <name>Lokesh Gupta</name> <title>Author</title> </employee> <employee id="102"> <name>Brian Lara</name> <title>Cricketer</title> </employee> </employees>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="department" type="department"/>
<xs:element name="employee" type="employee"/>
<xs:complexType name="employee">
<xs:sequence>
<xs:element ref="department" minOccurs="0"/>
<xs:element name="firstName" type="xs:string" minOccurs="0"/>
<xs:element name="id" type="xs:int" minOccurs="0"/>
<xs:element name="lastName" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="department">
<xs:sequence>
<xs:element name="id" type="xs:int" minOccurs="0"/>
<xs:element name="name" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
2. Schema Validation Errors
XSD validation against XML will not be always successful. Many times, you will get validation errors. These errors will be thrown as SAXException. So catch this exception and it will have the context where validation failed.
e.g. I have update the schema file with this change.
<xs:element name="firstName" type="xs:string" minOccurs="0"/> //to <xs:element name="firstName" type="xs:int" minOccurs="0"/>
Now look at validation error.
javax.xml.bind.UnmarshalException - with linked exception: [org.xml.sax.SAXParseException; systemId: file:/C:/Users/lokesh/workspace/App/employee.xml; lineNumber: 7; columnNumber: 34; cvc-datatype-valid.1.2.1: 'Lokesh' is not a valid value for 'integer'.] at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189) at com.howtodoinjava.demo.JaxbExample.jaxbXmlFileToObject(JaxbExample.java:45) at com.howtodoinjava.demo.JaxbExample.main(JaxbExample.java:23) Caused by: org.xml.sax.SAXParseException; systemId: file:/C:/Users/lokesh/workspace/App/employee.xml; lineNumber: 7; columnNumber: 34; cvc-datatype-valid.1.2.1: 'Lokesh' is not a valid value for 'integer'. at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203) at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:458) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3237) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3152) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3062) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2140) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:859) at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:584) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.endElement(ValidatingUnmarshaller.java:91) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:165) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2973) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243) ... 7 more
Drop me your questions in comments section.
Happy Learning !!
Обзор
Здравствуйте! В этой статье я хочу описать программу валидации 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.
Address.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ns:Request xmlns:ns="http://www.tempuri.org/types">
<Version>V001.000.00</Version>
<Address>
<Apartment>50</Apartment>
<House>7</House>
<Street>Sadovaya</Street>
<City>SPB</City>
<Country>Russia</Country>
<Index>123456</Index>
</Address>
</ns:Request>
Client.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ns:Request xmlns:ns="http://www.tempuri.org/types">
<Version>V001.000.00</Version>
<Client>
<Id>12</Id>
<Name>A</Name>
</Client>
<Client>
<Id>34</Id>
<Name>B</Name>
</Client>
</ns:Request>
Далее определим XSD-схемы XmlValidator.xsd, ComplexTypes.xsd и SimpleTypes.xsd с
описанием контейнера CombinedType и объектов типа Address и Client:
XmlValidator.xsd:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsd:schema xmlns:ns="http://www.tempuri.org/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ict="complextypes"
targetNamespace="http://www.tempuri.org/types"
elementFormDefault="qualified">
<xsd:import namespace="complextypes" schemaLocation="complextypes.xsd"/>
<xsd:annotation>
<xsd:documentation>XSD structure</xsd:documentation>
</xsd:annotation>
<xsd:element name="Combined" type="ict:CombinedType">
<xsd:annotation>
<xsd:documentation>XML definition</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:schema>
ComplexTypes.xsd
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="complextypes"
xmlns:ist="simpletypes"
targetNamespace="complextypes">
<xsd:import namespace="simpletypes" schemaLocation="simpletypes.xsd"/>
<xsd:complexType name="CombinedType">
<xsd:sequence>
<xsd:element name="Version" type="ist:VersionType">
<xsd:annotation>
<xsd:documentation>The version</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:choice>
<xsd:element name="Address" type="AddressType" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Address type</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="Client" type="ClientType" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>Client type</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="AddressType">
<xsd:sequence>
<xsd:element name="Apartment" type="ist:ApartmentType">
<xsd:annotation>
<xsd:documentation>Apartment number</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="House" type="ist:HouseNumberType">
<xsd:annotation>
<xsd:documentation>House number</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="Street" type="ist:StreetType">
<xsd:annotation>
<xsd:documentation>Street name</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="City" type="ist:CityType">
<xsd:annotation>
<xsd:documentation>City name</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="Country" type="ist:CountryType">
<xsd:annotation>
<xsd:documentation>Country name</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="Index" type="ist:IndexType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>Postal index</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ClientType">
<xsd:sequence>
<xsd:element name="Id" type="ist:IdType">
<xsd:annotation>
<xsd:documentation>The id</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="Name" type="ist:NameType">
<xsd:annotation>
<xsd:documentation>The name</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
SimpleTypes.xsd
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="simpletypes"
targetNamespace="simpletypes">
<xsd:simpleType name="VersionType">
<xsd:annotation>
<xsd:documentation>V000.000.00</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="11"/>
<xsd:pattern value="V[0-9]{3}.[0-9]{3}.[0-9]{2}"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="IdType">
<xsd:annotation>
<xsd:documentation>Int, 10 max</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:nonNegativeInteger">
<xsd:totalDigits value="10"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="NameType">
<xsd:annotation>
<xsd:documentation>String, 50 max</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="50"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ApartmentType">
<xsd:annotation>
<xsd:documentation>Int, 4 max</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:nonNegativeInteger">
<xsd:totalDigits value="4"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="HouseNumberType">
<xsd:annotation>
<xsd:documentation>Int, 3 max</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:nonNegativeInteger">
<xsd:totalDigits value="3"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="StreetType">
<xsd:annotation>
<xsd:documentation>String, 40 max</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="40"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="CityType">
<xsd:annotation>
<xsd:documentation>City, 40 max</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="40"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="CountryType">
<xsd:annotation>
<xsd:documentation>Country, 30 max</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="30"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="IndexType">
<xsd:annotation>
<xsd:documentation>Int, 10 max</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:nonNegativeInteger">
<xsd:totalDigits value="10"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Обратите внимание на элемент <xsd:choice> в CombinedType схемы ComplexTypes.xsd. Он означает, что xml-файл должен содержать либо один элемент типа Address, либо один или несколько элементов типа Client.
2. Конфигурация Spring
В файле spring-config.xml находится описание используемых в проекте бинов Printer,
FileReader, Marshaller, XMLService. Помимо указанных бинов, определен фильтр расширений
FileNameExtensionFilter, чтобы рассматривать только xml-файлы.
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<!-- Printer -->
<bean id="printer" class="com.xmlprocessor.service.impl.AnsiConsolePrinter"/>
<!-- FilenameExtensionFilter -->
<bean id="filenameExtensionFilter"class=
"com.xmlprocessor.util.FilenameExtensionFilter">
<constructor-arg index="0">
<list>
<value>xml</value>
</list>
</constructor-arg>
</bean>
<!-- FileReader -->
<bean id="fileReader" class="com.xmlprocessor.service.impl.FileReader">
<property name="filenameFilter" ref="filenameExtensionFilter" />
</bean>
<!-- Marshaller -->
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.xmlprocessor.types.CombinedType</value>
</list>
</property>
<property name="schemas">
<list>
<value>xmlvalidator.xsd</value>
<value>complextypes.xsd</value>
<value>simpletypes.xsd</value>
</list>
</property>
<property name="marshallerProperties">
<map>
<entry>
<key>
<util:constant static-field=
"javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT"/>
</key>
<value type="java.lang.Boolean">true</value>
</entry>
</map>
</property>
</bean>
<!-- XmlService -->
<bean id="xmlService" class="com.xmlprocessor.service.impl.XmlService">
<property name="printer" ref="printer" />
<property name="marshaller" ref="marshaller" />
<property name="unmarshaller" ref="marshaller" />
</bean>
</beans>
3. Преобразование XML-Java
В точке входа приложения XmlProcessorDrv сначала считываем и проверяем аргументы
командной строки, затем через вызов методов класса Compositor создаем бины printer,
fileReader и xmlService. Далее считываем xml-файлы и выполняем валидацию файлов в
директории, указанной в CLI_OPTION_DIRECTORY.
Самое интересное происходит при вызове
xmlService.validate(xmlFiles)
XmlProcessorDrv
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 {@value} for OK. */
private static final int EXIT_STATUS_OK = 0;
/** Exit Status {@value} 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%sn", 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<File> xmlFiles;
XmlServiceInt xmlService = Compositor.getXmlService();
try {
xmlFiles = Compositor.getFileReader().readFiles(dir);
printer.bold("nnStart 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 представлен ниже.
XmlService.java
...
/** {@inheritDoc} */
public void validate(List<File> 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…
В итоге:
AddressType.java
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;
/**
* <p>Java class for AddressType complex type.</p>
*/
@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();
}
}
ClientType.java
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();
}
}
CombinedType.java
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;
/**
* <p>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 List<ClientType> clients;
@XmlElement(name = "Address")
protected AddressType address;
public String getVersion() {
return version;
}
public void setVersion(String value) {
this.version = value;
}
public List<ClientType> getClients() {
if (clients == null) {
clients = new ArrayList<ClientType>();
}
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 <Dir>] [-h] [-v]
-h,--help Display this help
-v Version of the program
-d <Dir> 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:
Address_with_error
<?xml version="1.0" encoding="UTF-8"?>
<ns:Combined xmlns:ns="http://www.tempuri.org/types">
<Version>V001.000.00</Version>
<Address>
<AApartment>50</Apartment>
<House>7</House>
<Street>Sadovaya</Street>
<City>Saint Petersburg</City>
<Country>Russia</Country>
<Index>123456</Index>
</Address>
</ns:Combined>
В этом случае программа выдаст ошибку:
Спасибо за внимание.
Introduction to XML Validation
XML validation is a process done to check for a syntax error in an XML document to ensure that the document is well-written with the standard rules using either DTD or schema. A complete XML file is considered to be valid XML document unless it has correct syntax and constraints defined in it. To check for the validation document type definitions follow two schemas and it is checked for well-doing so no need to consider the data and structure of the XML document. For instance, if the data is the location and the first name, validation works if the respective values are provided without non-empty. Validation is preferred to make sure that XML file is sent between a client and the server which does the service of web service that is acknowledged correctly.
Syntax:
1. For DTD to validate the code
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT name (child elements, *)>
<!ELEMENT
<!ATTLIST
Att name CDATA #REQUIRED
Att name CDATA #IMPLIED
>
2. For XSD
<?xml version="1.0" encoding="UTF-8">
<xsd:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsd:element name="">
<xsd:complexType>
<xsd:sequence>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
How does Validation work in XML?
- Validation Process is dealt with XML Parser in two different ways.
- One is Well-defined XML Document and another one is Valid XML Document.
- Validation is optional but when it is about data integrity it is highly recommended.
- In most of the cases, validation of XML is done through schemas, not by DTD.
- The XML parser plays the main role in Validation has two categories like validating and non-validating.
- Former validate against DTD and later doesn’t validate XML with respective to DTD.
Associating XML Document with DTD
XML document done with correct syntax is termed to be well-formed and it should be validated appropriately with Document Type Definition (DTD.) It checks the vocabulary and grammatic rules. Applications that make use of XML documents should match the data with the corresponding definitions and validation lies on post-processing. Validation can be performed either using Validation tools like IDE and through on-line validators.
Validating XML file with DTD requires:
- XML File
- DTD document where DTD is a collection of elements and attributes.
Once the above two processes are done it is required to parse a xml file using function parser () which automatically generates Document Object Tree using DOM API in java. This parser reports warning messages at the end of the validation processing. Next is to enabling setvalidating () method to “TRUE”. We can also validate the file using NetBean. Since DTS doesn’t support Namespaces a basic drawback for XML DTD validation. To overcome this XML it has an advantage of using Schema Validation.
Associating XML Document with XML Schema
XML Schema is also termed as XML Schema Definition defines a newer way to validate XML fragment. Schemas are necessary when transferring the structure of the XML document to a machine. Validating means running a process to ensure that the XML Document proceeds the rules defined by the standard schemas.
Speaking, schemas are validated due to data completeness of checking the required information, a data structure of the elements and attributes are corrected like the order of child elements. Also, there are some tools published by the industry to perform these great checks. Even though schemas are validated in some cases it is not as simple. In some cases it may pass validation but leaving a warning message.
Examples of XML Validation
Given below are the examples mentioned:
Example #1
Here we are going to write XML file for Hospital and save the file as dr.xml.
Code:
dr.xml
<?xml version = "1.0" ?>
<!DOCTYPE Hospital SYSTEM "Hospital.dtd">
<Doctor>
<D_Id> D-003 </D_Id>
<D_Name> Joy Angeline </D_Name>
<Gender> Female </Gender>
<E_ID> Vinod1@yahoo.com </E_ID>
</Doctor>
Next, DTD file is generated for the above XML file where the document starts with <[ ]>.
Hospital.dtd
<!ELEMENT Doctor (D_Id, D_Name,Gender,E_ID)>
<!ELEMENT D_Id (#PCDATA)>
<!ELEMENT D_Name (#PCDATA)>
<!ELEMENT Gender (#PCDATA)>
<!ELEMENT E_ID (#PCDATA)>
If the validation is not successfully done it is necessary to modify the XML document to make well-formed XML Document.
Note: In this example, we have used Notepad++ for dtd validation. Before executing follow the steps to plugins xml tool. Go to notepad++ -> click plugins ->Plugin Manager -> generate XML tool (automatically updates in the list)and click ok button. Then in the toolbar, you could see plugins-> XML tools, right-click and click validate now. The DTD is validated for the corresponding xml file. (create dr.xml and Hospital.dtd in the notepad++) then click xml file and follow the above procedure to check for validation.
Output:
Plugin Installation
After Validating
Example #2
Using Java XML file and XSD are validated.
Code:
ps.xml
<?xml version = "1.0"?>
<grade>
<stud id = "435">
<firstname>joseph</firstname>
<lastname>raj</lastname>
<score>75</score>
</stud>
<stud id = "355">
<firstname>Vani</firstname>
<lastname>Neelakandan</lastname>
<score>95</score>
</stud>
<stud id= "555">
<firstname>Vinothalin</firstname>
<lastname>Stefen</lastname>
<score>88</score>
</stud>
</grade
sc.xsd
<xs:schemaattributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="grade">
<xs:complexType><xs:sequence><xs:element name="stud" maxOccurs="unbounded" minOccurs="0">
<xs:complexType><xs:sequence>
<xs:element type="xs:string" name="firstname"/>
<xs:element type="xs:string" name="lastname"/>
<xs:element type="xs:byte" name="score"/>
</xs:sequence>
<xs:attribute type="xs:short" name="id" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element></xs:schema>
Xmlv.java
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 Xmlv {
public static void main(String[] args) {
if(args.length !=2){
System.out.println( "XSDValidator<fname.xsd><fname.xml>" );
} else {
booleanisV = validateXMLSchema(args[0],args[1]);
if(isV){
System.out.println(args[1] + " is well-formed " + args[0]);
} else {
System.out.println(args[1] + " is not well-formed " + args[0]);
}
}
}
public static booleanvalidateXMLSchema(String xsdP, String xmlP){
try {
SchemaFactory factory =
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema s = factory.newSchema(new File(xsdP));
Validator validator = s.newValidator();
validator.validate(new StreamSource(new File(xmlP)));
} catch (IOException e1){
System.out.println("Exception: "+e1.getMessage());
return false;
}catch(SAXException e2){
System.out.println("SAX Exception: "+e2.getMessage());
return false;
}
return true;
}
}
Save all the three files in the same folder and execute in javajdk. (example e:javajavac file name).
Output:
Advantages of using Validation in XML
Given below are the advantages:
- If no validation the respective files cannot be viewed clearly. When using validation mismatches or missing information between the datasets can be viewed clearly.
- Does consistency and completeness.
- XML schema validation is preferred more than DTD validation probably the reason is the schema defines rules on the content and the document of XSD are themselves doe in XML which is unlike DTD grammar.
- Using XML Parser and XML Dom to resolve the error using validation.
- Also, it helps in matching the namespaces of a compiled schemas along with xmlns namespaces.
Conclusion
Therefore, in this article, we have seen xml validation mechanism and also saw XML DTD structures and schemas. It is quite difficult if the XML validation is big. Having validating using XML it is advisable to look on specific values and data relationships schema validation tool present only consistent results, therefore it is suggested to use validated tools. Choosing to use either DTD or schemas is always depending on what you do with XML. Some new technologies, especially web services,depending on the schemas.
Recommended Articles
This is a guide to XML Validation. Here we discuss the introduction to XML Validation, along with how does validation work, associating an XML document with DTD and advantages. You may also have a look at the following articles to learn more –
- XML Features
- XML in Excel
- XML Versions
- XML with CSS















