Click here to Skip to main content
15,899,754 members
Articles / Programming Languages / XML
Tip/Trick

XML Validator - Commandline Tool

Rate me:
Please Sign up or sign in to vote.
2.80/5 (3 votes)
27 Nov 2017CPOL1 min read 12K   207   7   1
It is a commandline XML/XSD validator

Introduction

This is a simple command prompt application to validate XML against XSD, i.e., XML schema file.

The intention being a new development is there are situations like running a make file to build a huge package that might include XML files at some point and need to be validated. Those XML files may require a specific rule or data type which checks item’s value range or in other words, user specific datatype.

Background

This is one such tool, exe can be used to make script during package build where validation is needed.

Implemented in C# solution as command based, and C# class DLL for core validation function and for log file. For error logging, log4net.dll is used which is freeware, reason being log4net enables logging simple.

The Code

ValidationUtils.dll - This includes the core implementation class and this DLL is added to solution‘s References.

C#
/// <summary>
/// This function creates an xml reader, and Loads the xml file selected for validation.
/// </summary>
/// <returns>bool</returns>

public bool OpenXmlFileUtils(string xml_path)
{
           if (xmlPath != xml_path)
                xmlPath = xml_path;

           try
            {
                //create a file reader to read xml and copy to string
                reader = XmlReader.Create(xml_path, readerSettings);

               //Load xml file   
                xmlDoc.Load(xml_path);

               //Close file               
               CloseXmlFile(reader);
               bResult = true;
            }
            catch (Exception)
            {
                bResult = false;
            }

            return bResult;
        }

/// <summary>
/// Main function for this tool, Validates xml against xsd with the help of
/// event handler function ValidationEventHandlerUtils.

public void ValidateXMLUtils(string testString, int iCount)
        {
            //initialize it to 0 before any handler called.
            nErrors = 0;

            try
            {
                // Declare local objects
                XmlReaderSettings rs = new XmlReaderSettings();
                rs.ValidationType = ValidationType.Schema;
                rs.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation |
                XmlSchemaValidationFlags.ReportValidationWarnings;
                // Event Handler for handling exception &
                // this will be called whenever any mismatch between XML & XSD

                rs.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandlerUtils);
                rs.Schemas.Add(null, XmlReader.Create(testString));
                xmlValidatingReader = XmlReader.Create(xmlPath, rs);
                ...
}

/// <summary>
/// Event handler method called by ValidateXMLUtils function.
/// </summary>
 void ValidationEventHandlerUtils(object sender, ValidationEventArgs e)
        {
            //Update failed count
            validationCalledCount++;
            if (e.Severity == XmlSeverityType.Warning)
            {
                validationResultStr = e.Message;
            }
…
}

Logging class implementation (wrapper to log4net APIs):

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using log4net;

namespace ValidationUtils
{
    public class LogFile
    {
        public bool results = false;
        //initializes log4net.
        private static readonly ILog logger =
        LogManager.GetLogger(typeof(LogFile));

        //for singleton
        public static LogFile logfile_instance;

        /// <summary>
        /// Ctor
        /// </summary>
        public LogFile()
        {
            log4net.Config.XmlConfigurator.Configure();
        }

        //for singleton
        public static LogFile cpeLogFileInstance
        {
            get
            {
                if (logfile_instance == null)
                {
                    logfile_instance = new LogFile();
                }

                return logfile_instance;
            }
        }
…
}

Example XML and XSD files used to capture output screenshot:

XML

XML
<?xml version="1.0" encoding="UTF-8"?>
<shiporder orderid="150">
  <orderperson>Raghavendra Hosad</orderperson>
  <shipto>
    <name>Raghavendra Hosad</name>
    <address>Green Park 55</address>
    <city>10 HYD</city>
    <country>India</country>
  </shipto>
  <item>
    <title>The Da Vinci Code</title>
    <note>Special Edition</note>
    <quantity>1</quantity>
    <price>8.50</price>
  </item>
  <item>
    <title>Harry Potter and the Goblet of Fire</title>
    <quantity>1</quantity>
    <price>12.30</price>
  </item>
</shiporder>

XSD

XML
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" 
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="shiporder">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="orderperson" type="xs:string" />
        <xs:element name="shipto">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="name" type="xs:string" />
              <xs:element name="address" type="xs:string" />
              <xs:element name="city" type="xs:string" />
              <xs:element name="country" type="xs:string" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element maxOccurs="unbounded" name="item">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="title" type="xs:string" />
              <xs:element minOccurs="0" name="note" type="xs:string" />
              <xs:element name="quantity" type="xs:unsignedByte" />
              <xs:element name="price" type="xs:decimal" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute name="orderid" type="xs:unsignedByte" use="required" />
    </xs:complexType>
  </xs:element>

  <xs:simpleType name="quantityType">
    <xs:annotation>
      <xs:documentation>carrierIndex range checking.</xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:unsignedByte">
      <xs:minInclusive value="2"/>
      <xs:maxInclusive value="4"/>
    </xs:restriction>
  </xs:simpleType>
  
</xs:schema>

Result

  1. When validation is success.

    Image 1

  2. When there is validation error.

    Image 2

LogFile.log

A logfile is getting generated at system path C:\Users\<name>\AppData\Local\SchemaValidatorCmdTool\LogFile.log

2017-11-25 1:8:26,972 [9] INFO  -------------------------------------------------------------
2017-11-25 1:8:26,979 [9] ERROR The 'quantity' attribute is invalid
2017-11-25 1:8:26,979 [9] WARN   The value '1' is invalid according to its datatype 'quantityType'
2017-11-25 1:8:26,979 [9] WARN   The MinInclusive constraint failed.
2017-11-25 1:8:26,979 [9] INFO  Total item failed count : 1
2017-11-25 1:8:26,979 [9] INFO  Total item pass count : 15
2017-11-25 1:8:26,979 [9] INFO  -------------------------------------------------------------

Conclusion

I believe choosing a particular schema validator tool depends upon one's requirement. There are GUI implementations of such tools available but as long as we are not bothered about editing an item and need to include during make build, I think this tool (SchemaValidatorCmdTool) is handy and also a LogFile.log generating which can be used for examining additional fail item information.

History

  • 27th November, 2017: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
Raghavendra Prasad Hosad having 8+ years experience in IT as a Software Engineer.

Comments and Discussions

 
Questiontest files work but 'real' case does nothing Pin
Member 1385097130-May-18 0:47
Member 1385097130-May-18 0:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.