Fluent Interface for Validation an XML Document

Fluent API or Fluent Interfaces
https://www.primaryobjects.com/2011/02/07/fluent-interfaces-in-c-net-with-expression-builder-method-chaining-and-rpg-games/

Fluent XML document validation 

Fluent Interface

An interface designed in a way that actions are chained together gives a fluent, readable and natural style of logic
https://en.wikipedia.org/wiki/Fluent_interface

  • It improves code readability and flow, like writing sentences
  • It is commonly used in query builders, configuration settings, and ORMs (like Entity Framework).

In this article you will have a POC (Proof of Concept) which uses a fluent interface for the steps needed to fully validate an XML document
A fluent interface fits perfectly with the step you need to go though in a specific ordering when you validate XML data

Interfaces we are going to use

  • Create Document
    • Create prepares the document for validation
  • Check syntax
    • First check document for syntax errors
  • Check structure
    • Next check the document for structural integrity, eg do schema validation
  • Check content
    • Basic validation is done we can check the document for the business requirements
  • Transform document
    • Or we are ready to style and transform the document to a readable presentation by using eg a stylesheet 
  • Result
    • Return the validation result

Main class to stich it all together

  • XMLValidator
    • Inherits
      • Document 
        • Create
      • ValidateSyntax
        • CheckSyntax
      • ValidateStructure
        • CheckStructure
      • Validated
        • CheckContent
        • TransformContent
      • ValidationResult
        • GetMessage (Result)

The resulting work flow

  • Fulfilment 
    1. Validation occurs in strict order or chain defined by the returned interface in the methods called
    2. Response is added to StringBuilder by each step
    3. Validation result is returned to user and thus the chain is terminated

POC of FluentValidator

All interfaces

Steps needed for the document object to be prober validated

// Interfaces used for building the fluent validator	
namespace FluentValidator.Interface
{
	/// <summary>
	/// Prepare document for validation
	/// </summary>
	public interface IDocument
	{
		public IValidateSyntax Create();
	}

	/// <summary>
	/// RuUn a syntax check on the document
	/// </summary>
	public interface IValidateSyntax
	{
		public IValidateStructure CheckSyntax();
	}

	/// <summary>
	///	Validate the structure of the document using a schema
	/// </summary>
	public interface IValidateStructure
	{
		public IValidated CheckStructure();
	}

	/// <summary>
	/// Document is structural and semantic valid
	/// </summary>
	public interface IValidated
	{
		public IValidationResult CheckContent();
		public IValidationResult TransformContent();
	}

	/// <summary>
	/// Return validation result
	/// </summary>
	public interface IValidationResult
	{
		public string GetMessage();
	}
}

The concrete class implementation using the interfaces we have created

using System.Text;
using FluentValidator.Interface;

namespace FluentValidator.Validator
{
	/// <summary>
	/// Concrete implementation of the fluent validator
	/// </summary>
	/// <seealso cref="FluentValidator.Interface.IValidateSyntax" />
	/// <seealso cref="FluentValidator.Interface.IValidateStructure" />
	/// <seealso cref="FluentValidator.Interface.IValidated" />
	/// <seealso cref="FluentValidator.Interface.IValidationResult" />
	/// <seealso cref="FluentValidator.Interface.IDocument" />
	public class ValidateXML : IValidateSyntax, IValidateStructure, IValidated, IValidationResult, IDocument
    {
        private StringBuilder message = new StringBuilder();

		/// <summary>
		/// Creates the instance.
		/// </summary>
		/// <returns></returns>
		public IValidateSyntax Create()
        {
            return new ValidateXML();
        }
		/// <summary>
		/// Checks the syntax.
		/// </summary>
		/// <returns>IValidateStructure</returns>
		public IValidateStructure CheckSyntax()
        {
            message.Append("Syntax validated\r\n");
            return this;
        }

		/// <summary>
		/// Checks the structure.
		/// </summary>
		/// <returns>IValidated</returns>
		public IValidated CheckStructure()
        {
            message.Append("Structure validated\r\n");
            return this;
        }

		/// <summary>
		/// Checks the content.
		/// </summary>
		/// <returns>IValidationResult</returns>
		public IValidationResult CheckContent()
        {
            message.Append("Content validated\r\n");
            return this;
        }

		/// <summary>
		/// Transforms the content.
		/// </summary>
		/// <returns>IValidationResult</returns>
		public IValidationResult TransformContent()
		{
			message.Append("Stylesheet applied\r\n");
			return this;
		}

		/// <summary>
		/// Gets the message.
		/// </summary>
		/// <returns>string</returns>
		public string GetMessage()
        {
            return message.ToString();
        }

    }
}

POC program to run

using FluentValidator.Validator;

namespace FluentValidator
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ValidateXML validate = new ValidateXML();

			Console.WriteLine("Validate XML file:");
			Console.WriteLine("------------------");

			Console.WriteLine(
                validate.Create()
                    .CheckSyntax()
                    .CheckStructure()
                    .CheckContent()
                    .GetMessage()
                );

			Console.WriteLine("");
			Console.WriteLine("Validate and transform XML file:");
			Console.WriteLine("--------------------------------");

			Console.WriteLine(
				validate.Create()
					.CheckSyntax()
					.CheckStructure()
					.TransformContent()
					.GetMessage()
				);

			Console.ReadKey();
        }
    }
}

Console output from the program

Validate XML file:
------------------
Syntax validated
Structure validated
Content validated


Validate and transform XML file:
--------------------------------
Syntax validated
Structure validated
Stylesheet applied

 

Try the example at Fiddle

https://dotnetfiddle.net/gqNieE

 

Comments are closed