The article by Josh on XHTML Validator is the best stuff available. It is very simple to deploy and use. I myself used this for logging the XHTML validation errors in the log file using Custom Renderer option. I’m putting the code for CustomRenderer below
Step 1:
Create a class that implements the IValidationRenderer.
Step 2:
Implement the Render method as follows
public void Render(HttpResponse response, Collection<ValidationRecord> errors,
TimeSpan validationDuration)
{ String CSVFilePath = null; String url = HttpContext.Current.Request.RawUrl;
String[] urlComponent = url.Split('/');
CSVFilePath = HttpContext.Current.Server.MapPath("/" + urlComponent [1]) + "\\Errors.csv"; this.createHeader(CSVFilePath);
this.logErrors(errors, CSVFilePath); } private void logErrors(Collection<ValidationRecord> errors, String CSVFilePath)
{
StreamWriter csvWriter = new StreamWriter(CSVFilePath, true);
string browser = HttpContext.Current.Request.Browser.Type;
string url = HttpContext.Current.Request.RawUrl;
foreach (ValidationRecord record in errors)
{
StringBuilder logRecord = new StringBuilder();
logRecord.AppendFormat("{0},{1},{2},{3},{4},{5}", browser, url,
record.LineNumber, record.LinePosition,
record.Severity, record.Message.Replace(',',' '));
csvWriter.WriteLine(logRecord.ToString());
}
csvWriter.Close();
}
private void createHeader(String CSVFilePath)
{
if (File.Exists(CSVFilePath) == false)
{
StreamWriter csvWriter = new StreamWriter(CSVFilePath, true);
StringBuilder logRecord = new StringBuilder();
logRecord.Append("Browser,Url,LineNumber,LinePosition,Severity,Message");
csvWriter.WriteLine(logRecord.ToString());
csvWriter.Close();
}
}
Step 3:
Do the following change in the Web.Config file
<validatorModule enabled="true" mode="Custom" customRenderer="XHTMLLogWriter,XHTMLValidator">
The above code creates the CSVFile name Errors.csv at the virtual directory physical path.
String url = HttpContext.Current.Request.RawUrl;
String[] urlComponent = url.Split('/');
CSVFilePath = HttpContext.Current.Server.MapPath("/" + urlComponent [1]) + "\\Errors.csv";
The createHeader method creates the header of the csv file and logErrors method log each error in the csv file by iterating through the collection.
This dumps the following in the CSV file
- Browser: The name of the browser.
- Url: The Url of the Page.
- LineNumber: The Line Number where the error occurred.
- LinePosition: The position within the line.
- Severity: Severity of the error.
- Message: Error Message.
The below is the snapshot of the csv file generated

I hope this helps you guys and thanks once again to Josh for the great work.

