/// <summary>
		/// Derived classes can call AddUserError() to add errors or warnings or else to the existing list
		/// of parsing/validation errors.
		/// The IsValid flag will be set to false if error severity is Error or Fatal.
		/// </summary>
		/// <param name="severity">Error severity</param>
		/// <param name="message">Message</param>
		/// <param name="line">Source line</param>
		public void  AddValidationMessage ( XmlParseErrorSeverity  severity, string  message, int  line = 0 )
		   {
			XmlParseError	pe	=  new XmlParseError ( ) ;

			pe. Step		=  XmlParseStep. UserValidation ;
			pe. Severity		=  severity ;
			pe. Message		=  message ;
			pe. Line		=  line ;
			pe. Column		=  0 ;
			pe. Source		=  "xml document" ;
			pe. SourceUri		=  "xml document" ;

			ValidationMessages. Add ( pe ) ;				   
			SetValidState ( pe. Severity ) ;
		    }
		/// <summary>
		/// Builds and validates an Xml document.
		/// </summary>
		/// <param name="xml_data">Xml contents, specified as a string</param>
		/// <param name="xsd_data">Xsd specifications, specified as a string</param>
		public XmlValidatedDocument ( string		xml_data, 
					      string		xsd_data	=  null ) : base ( )
		    {
			// Initializations
			IsValid			=  true ;			// Consider that by default the document is valid until some crap is found
			ValidationMessages	=  new XmlParseErrors ( ) ;
			XmlData			=  xml_data ;			// Remember supplied parameters
			XsdData			=  xsd_data ;
			
			// Step 1 : load xml data
			try
			   {
				LoadXml ( xml_data ) ;
			    }
			// Catch parsing errors such as opening/closing tag mismatch, or attribute with no value
			catch ( XmlException  e )
			   {
				XmlParseError	pe	=  new XmlParseError ( ) ;

				IsValid			=  false ;
				pe. Step		=  XmlParseStep. XmlParsing ;
				pe. Severity		=  XmlParseErrorSeverity. Error ;
				pe. Message		=  e. Message ;
				pe. Line		=  e. LineNumber ;
				pe. Column		=  e. LinePosition ;
				pe. Source		=  e. Source ;
				pe. SourceUri		=  e. SourceUri ;

				ValidationMessages. Add ( pe ) ;
			    }

			// Stop here if step 1 failed : validation cannot be performed on syntactically incorrect xml data
			if  ( ! IsValid ) 
				return ;

			// Perform steps 2 (Xsd validation) and 3 (Xml validation using Xsd) only if xsd data has been specified
			if  ( xsd_data  !=  null )
			   { 
				// Step 2 : Validate the xsd itself before using it for validating the xml...
				XmlSchema		schema		=  XmlSchema. Read
				   (
					new StringReader ( xsd_data ),
					( object  sender, ValidationEventArgs  e ) =>
					   {
						XmlParseError	pe	=  new XmlParseError ( ) ;

						pe. Step		=  XmlParseStep. XsdValidation ;
						pe. Severity		=  ( XmlParseErrorSeverity ) e. Severity ;
						pe. Message		=  e. Message ;
						pe. Line		=  e. Exception. LineNumber ;
						pe. Column		=  e. Exception. LinePosition ;
						pe. Source		=  e. Exception. Source ;
						pe. SourceUri		=  e. Exception. SourceUri ;

						ValidationMessages. Add ( pe ) ;
						SetValidState ( pe. Severity ) ;
					     }
				    ) ;

				// Stop here if xsd contain errors : we will not be able to use it for xml validation anyway
				if  ( ! IsValid )
					return ;

				// Step 3 : validate the xml document using the xsd schema
				Schemas. Add ( schema ) ;
		
				Validate
				   ( 
					( object  sender, ValidationEventArgs  e ) =>
					   {
						XmlParseError	pe	=  new XmlParseError ( ) ;

						pe. Step		=  XmlParseStep. XmlValidation ;
						pe. Severity		=  XmlParseErrorSeverity. Error ;
						pe. Message		=  e. Message ;
						pe. Line		=  e. Exception. LineNumber ;
						pe. Column		=  e. Exception. LinePosition ;
						pe. Source		=  e. Exception. Source ;
						pe. SourceUri		=  e. Exception. SourceUri ;

						ValidationMessages. Add ( pe ) ;				   
						SetValidState ( pe. Severity ) ;
					    }
				    ) ;

				// Stop here if validation failed ; there is no need to perform user processing at that stage
				if  ( ! IsValid )
					return ;
			    }

			// Step 4 : everything went smooth (perhaps we had some informational or warning messages), so
			//          we can perform user processing.
			ValidateStructure ( ) ;
		     }