A practical guide to XSD tools available in .NET8 environment.
Abstract: A practical guide to XML and XSD tools available in .NET8 environment, focusing on generating and using C# classes to process some XML valid for some given XSD (technology as of September 2024).
1 Doing XML and XSD related work in .NET8
I was recently doing some work related to XML and XSD processing in .NET8 environment and created several proof-of-concept applications to evaluate the tools available. These articles are the result of my prototyping work.
1.1 List of tools used/tested
Here are the tools used/tested:
- Visual Studio 2022
- XSD.EXE (Microsoft license, part of VS2022)
- XmlSchemaClassGenerator (Open Source/Freeware)
- LinqToXsdCore (Open Source/Freeware)
- Liquid XML Objects (Commercial license)
1.2 Articles in this series
For technical reasons, I will organize this text into several articles:
- XSD Tools in .NET8 – Part1 – VS2022
- XSD Tools in .NET8 – Part2 – C# validation
- XSD Tools in .NET8 – Part3 – XsdExe – Simple
- XSD Tools in .NET8 – Part4 – XsdExe - Advanced
- XSD Tools in .NET8 – Part5 – XmlSchemaClassGenerator – Simple
- XSD Tools in .NET8 – Part6 – XmlSchemaClassGenerator – Advanced
- XSD Tools in .NET8 – Part7 – LinqToXsdCore – Simple
- XSD Tools in .NET8 – Part8 – LinqToXsdCore – Advanced
- XSD Tools in .NET8 – Part9 – LiquidXMLObjects – Simple
- XSD Tools in .NET8 – Part10 – LiquidXMLObjects – Advanced
2 Examples of XML and XSD
Some sample XML-s and XSD-s I created for test purposes.
2.1 Simple case
<?xml version="1.0" encoding="utf-8"?> <!--SmallCompany.xsd++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="https://markpelf.com/SmallCompany.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="SmallCompany"> <xs:complexType> <xs:sequence> <xs:element name="CompanyName" type="xs:string" /> <xs:element maxOccurs="unbounded" name="Employee"> <xs:complexType> <xs:sequence> <!--Name_String_NO is String NotOptional--> <xs:element name="Name_String_NO" type="xs:string" /> <!--City_String_O is String Optional--> <xs:element minOccurs="0" name="City_String_O" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element maxOccurs="unbounded" name="InfoData"> <xs:complexType> <xs:sequence> <!--Id_Int_NO is Int NotOptional--> <xs:element name="Id_Int_NO" type="xs:int" /> <!--Quantity_Int_O is Int Optional--> <xs:element minOccurs="0" name="Quantity_Int_O" type="xs:int" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Valid XML
<?xml version="1.0" encoding="utf-8"?> <!--SmallCompany.xsd++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="https://markpelf.com/SmallCompany.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="SmallCompany"> <xs:complexType> <xs:sequence> <xs:element name="CompanyName" type="xs:string" /> <xs:element maxOccurs="unbounded" name="Employee"> <xs:complexType> <xs:sequence> <!--Name_String_NO is String NotOptional--> <xs:element name="Name_String_NO" type="xs:string" /> <!--City_String_O is String Optional--> <xs:element minOccurs="0" name="City_String_O" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element maxOccurs="unbounded" name="InfoData"> <xs:complexType> <xs:sequence> <!--Id_Int_NO is Int NotOptional--> <xs:element name="Id_Int_NO" type="xs:int" /> <!--Quantity_Int_O is Int Optional--> <xs:element minOccurs="0" name="Quantity_Int_O" type="xs:int" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Invalid XML
<?xml version="1.0" encoding="utf-8"?> <!--SmallCompanyAAA.xml+++++++++++++++++++++++++++++++++++++++++++++++--> <SmallCompany xmlns="https://markpelf.com/SmallCompany.xsd"> <CompanyName>SmallCompanyAAA</CompanyName> <Employee> <Name_String_NO>Mark</Name_String_NO> <City_String_O>Belgrade</City_String_O> </Employee> <Employee> <Name_String_NO>John</Name_String_NO> </Employee> <InfoData> <Id_Int_NO>11</Id_Int_NO> <Quantity_Int_O>123</Quantity_Int_O> </InfoData> <InfoData> <Id_Int_NO>22</Id_Int_NO> </InfoData> <Offending_Element> Bla_Bla </Offending_Element> </SmallCompany>
2.2 Advanced case
Same as in the previous article.
3 Validation in C
Writing C# code to “validate XML for some XSD” is pretty basic, but still the right starting point.
3.1 C# code
Here is a sample code to do XML validation in C# for some XSD.
public static bool ValidateXmlForXsd( Microsoft.Extensions.Logging.ILogger? _logger, string xmlPath, string xsdPath) { bool isValid=false; XmlDocument xml = new XmlDocument(); xml.Load(xmlPath); xml.Schemas.Add(null, xsdPath); try { xml.Validate(null); isValid = true; } catch (XmlSchemaValidationException ex) { string text1 = $"Validation FAILED for: xmlPath={xmlPath}" + $" and xsdPath={xsdPath} .Validation Error: " + ex.Message; _logger?.LogInformation(text1); isValid = false; } if (isValid) { string text1 = $"Validation SUCCESS for: xmlPath={xmlPath}" + $" and xsdPath={xsdPath}"; _logger?.LogInformation(text1); } return isValid; }
3.2 Success case log
Here is the log of the validation success case.
XsdExample01-Start------------ xmlFile11_FullPath: C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\SmallCompanyAAA.xml xsdFile1_FullPath: C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\SmallCompany.xsd xmlFile21_FullPath: C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\BigCompanyMMM.xml xsdFile2_FullPath: C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\BigCompany.xsd Validation SUCCESS for: xmlPath=C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\SmallCompanyAAA.xml and xsdPath=C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\SmallCompany.xsd Validation SUCCESS for: xmlPath=C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\BigCompanyMMM.xml and xsdPath=C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\BigCompany.xsd XsdExample01-End------------
3.3 Failure case log
Here is the log of the validation failure case.
XsdExample01-Start------------ xmlFile11_FullPath: C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\SmallCompanyAAA.xml xsdFile1_FullPath: C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\SmallCompany.xsd xmlFile21_FullPath: C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\BigCompanyMMM.xml xsdFile2_FullPath: C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\BigCompany.xsd Validation FAILED for: xmlPath=C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\SmallCompanyAAA.xml and xsdPath=C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\SmallCompany.xsd . Validation Error: The element 'SmallCompany' in namespace 'https://markpelf.com/SmallCompany.xsd' has invalid child element 'Offending_Element' in namespace 'https://markpelf.com/SmallCompany.xsd'. List of possible elements expected: 'InfoData' in namespace 'https://markpelf.com/SmallCompany.xsd'. Validation SUCCESS for: xmlPath=C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\BigCompanyMMM.xml and xsdPath=C:\TmpXSD\XsdExample_Validate\Example01\bin\Debug\net8.0\XmlFiles\BigCompany.xsd XsdExample01-End------------
The full example code project can be downloaded at GitHub [99].
4 References
[1] XML Schema
https://www.w3schools.com/xml/xml_schema.asp
[2] The Difference Between Optional and Not Required
https://www.infopathdev.com/blogs/greg/archive/2004/09/16/The-Difference-Between-Optional-and-Not-Required.aspx
[3] nillable and minOccurs XSD element attributes
https://stackoverflow.com/questions/1903062/nillable-and-minoccurs-xsd-element-attributes
Top comments (0)