default heading
Only $4.95/month ASP.NET Hosting - Click Here!
Get a FREE MS SQL 2008 Database and have the ability to host UNLIMITED Web Sites under one account. NO Long Term Contracts and NO Setup Fees. Click Here and Sign Up Today with Winhost!
Google


 

			Only $4.95/month - Powerful ASP.NET Hosting...Click here!

Article Rating:  2.24
Upload an XML File and Validate Against a Schema...
By: John Kilgo Date: November 15, 2002 Download the code. Printer Friendly Version


This ASP.Net (VB) program allows you to locate an XML file on your local machine, or anywhere on your network for that matter, upload it to a web server and validate the file against an XML Schema existing on the web server. If the xml file validates, a success notification is provided. If the validation fails, either because your xml file is malformed, or because the data does not match the requirements listed in your schema, an html file will be produced containing a table of errors and the error locations.

If you donwload this project you will find an example xml file referencing a schema on this web site. You may use this for testing. Experiment with the xml file, introducing errors to see the output of the program. For your own use, you must point your xml file to a schema on your web server, or somewhere on your network.

The first program shown is the .aspx file which implements the file upload. Control is then turned over to the code behind page.

 <%
 ' Program: XmlValidateCB1.aspx
 ' By: John Kilgo
 ' Date: October 21, 2002
 ' CodeBehind: XmlValidatCB1.aspx.vb
 ' Purpose: Uploads an XML file and validates against a 
 ' Schema. Produces an html file showing errors if any.
 %>
 <%@Page Inherits="XmlValidateCB1" Src="XmlValidateCB1.aspx.vb" %>
 <% Response.Expires = -1444 %>
 <HTML>
 <META HTTP-EQUIV="Pragma" CONTENT='no-cache'>
 <HEAD>
 <TITLE>XmlValidateCB1.aspx</TITLE>
 </HEAD>
 <BODY>
 <FORM enctype="multipart/form-data" runat="server" ID="Form1">
 Select File to Validate:
 <INPUT type="file" 
     id="txtSelectedFile"
     runat="server"
     NAME="txtSelectedFile">
 <P>
 <INPUT type="button"
     id="btnValidate"
     value="Validate"
        OnServerClick="btnValidate_Click"
     Runat="server"
     NAME="validate">
 </P>
 <asp:Label ID="lblMessage"
         Runat="server" />
 </FORM>
 </BODY>
 </HTML> 
Next is the code behind file XmlValidateCB1.aspx.vb. Please note that the guts of this code was taken from the book "ASP.NET: Tips, Tutorials and Code". I changed it from C# to VB and added to it considerably, but I want to give credit where credit is due. First, the Namespaces involved:
 Imports System
 Imports System.Web
 Imports System.Web.UI
 Imports System.Web.UI.WebControls
 Imports System.Web.UI.HtmlControls
 Imports System.IO
 Imports System.IO.FileStream
 Imports System.Text
 Imports System.Xml
 Imports System.Xml.Schema 
Next is the main class declaration and the Click event code for the button on the .aspx page. Notice that most of the code is in a Try-Catch block. This will catch some, but not all files the user may select which are not XML files. The Session ID is used to build a unique file name for the errors page if needed. Since the same Session ID gets used much more often than I thought it would, the "unique" file named is deleted before it is used. If the file does not exist the File.Delete fails silently. The XML file gets saved in a specific directory, "d:\xmluploads" in my case. You may need to change that directory to suit your needs. "ValidatorVB" is a class defined a little further down in the code, so an object for it gets created in this section and the object is called. A boolean variable holds the return from the object. It is then evaluated to print a success or fail message for the user. The fail message includes a link to the html file containing the table of error messages and locations.
 Public Class XmlValidateCB1 : Inherits Page
   Protected txtSelectedFile As HtmlInputFile
   Protected lblMessage As Label
   Sub btnValidate_Click(source As Object, e As EventArgs)
     If Not (txtSelectedFile.PostedFile.FileName = "") Then
       Try
         Dim strFilePath As String
         Dim postedFile = txtSelectedFile.PostedFile
         Dim strFileName As String = Path.GetFileName(postedFile.FileName)
         Dim strSession As String = Session.SessionID
         Dim blnStatus as Boolean
         Dim strLogFile As String = Server.MapPath(strSession & ".htm")
         postedFile.SaveAs("d:/xmluploads/" & strFileName)
         strFilePath = "d:/xmluploads/" & strFileName
         File.Delete(Server.MapPath(strSession & ".htm"))
         Dim objValidate As ValidatorVB = New ValidatorVB( _
           strFilePath, strLogFile, True)
 
         'Call method to process XML document
         blnStatus = objValidate.Validate()
         If (blnStatus) Then
           lblMessage.Text = "Validation of " & strFileName & " was SUCCESSFUL!"
         Else
           lblMessage.Text = "Validation of " & strFileName & " failed! Check the 
                           log file for information on the failure 
                           (< a href=http://www.dotnetjohn/" & strSession & ".htm" & 
                             ">View Errors</a>)."
         End If
       Catch exc As Exception
         lblMessage.Text = "Failed validating file"
       End Try
     End If
   End Sub ' btnValidate_Click  
Next is the ValidatorVB class. Most of the variables to read the XML file and do the actual validation are done here, and a Sub New is used to instantiate the class.
 Public Class ValidatorVB
     Dim blnHasDataError As Boolean = False
     Dim blnIsValid As boolean = True
     Dim _logError As boolean = True
     Dim _logFile As string = ""
     Dim _xmlFilePath As string = ""
     Dim xmlReader As XmlTextReader
     Dim validatingReader As XmlValidatingReader
     Dim validHandler As ValidationEventHandler
     Dim strHtml As String
     Dim blnFirst As Boolean = True
 
     Public Sub New(strFilePath As String, strLogFile As String, blnLogError As Boolean)
       _xmlFilePath = strFilePath
       _logFile = strLogFile
       _logError = blnLogError
     End Sub 
The class continues with a public function to do the actual validation. An XmlTextReader and a XmlValidating reader are created and the ValidationType is set to a schema. A ValidationEventHandler is also instantiated. The code for the above, as well as for reading the XML file are contained within a Try block. Two Catch blocks are used in order to catch both mal-formed xml and bad data according to the schema. A Finally block is used to close the readers. The variable blnHasDataError is checked to see to see if the error was bad data per the schema vs. missing or inconsistent xml tags. If the error was due to the xml file being mal-formed, that error message is created immediately and processing stops. If the problem was bad data per the schema, then the error message(s) are generated in the validation call back code.
 Public Function Validate() As Boolean
     Dim strErrorMsg As String
       Try
         xmlReader = new XmlTextReader(_xmlFilePath)
         validatingReader = new XmlValidatingReader(xmlReader)
         validatingReader.ValidationType = ValidationType.Schema
         validHandler = new ValidationEventHandler(addressof ValidationCallBack)
         AddHandler validatingReader.ValidationEventHandler, validHandler
         'Parse through XML
         While (validatingReader.Read())
 
         End While
       Catch a As UnauthorizedAccessException
         strErrorMsg = a.Message
       Catch a As Exception
         strErrorMsg = a.Message
         blnIsValid = False
       Finally
         'Close readers
         If (xmlReader.ReadState <> ReadState.Closed) Then
           xmlReader.Close()
         End If
         If (validatingReader.ReadState <> ReadState.Closed) Then
           validatingReader.Close()
         End If
       End Try
       If blnHasDataError = False Then
         Dim writer as StreamWriter
         writer = new StreamWriter(_logFile, true, Encoding.ASCII)
         writer.WriteLine("<html><head><title>ValidationLog</title></head>")
         writer.WriteLine("<body>")
         writer.WriteLine("<table border=1>")
         writer.WriteLine("<th>")
         writer.WriteLine("Validation error in: " & _xmlFilePath)
         writer.WriteLine("</th>")
         writer.WriteLine("<tr bgcolor=#6666CC>")
         writer.WriteLine("<td><font color=white><b>Error Message _
           </b></font></td>")
         writer.WriteLine("</tr>")
         writer.WriteLine("<tr bgcolor=D5CCBB>")
         writer.WriteLine("<td width=100%>")
         writer.WriteLine(strErrorMsg)
         writer.WriteLine("</td>")
         writer.WriteLine("</tr>")
         writer.Flush()
         writer.Close()
       End If
       Return blnIsValid
     End Function ' Validate() 
The next and last section is the ValidationCallBack and the ending of the master class. If processing hits this section then there is bad data per the schema contained in the XML file. Since there may be more than one instance of bad data a boolean variable is used to create the opening html and html table creation only once. Without some mechanism such as this, the html document headings and the table could be created more than once resulting in a pretty ugly html file. A StreamWriter is used to write out the html for the error log. The stream writer is closed in the Finally block.
 Private Sub ValidationCallBack(sender as object, args as ValidationEventArgs)
       blnIsValid = False  'hit callback so document has a problem
       Dim writer as StreamWriter
 
       Try
         If (_logError) Then
           blnHasDataError = True
           If blnFirst Then
             writer = new StreamWriter(_logFile, true, Encoding.ASCII)
             writer.WriteLine("<html><head><title>ValidationLog</title></head>")
             writer.WriteLine("<body>")
             writer.WriteLine("<table border=1>")
             writer.WriteLine("<th colspan=2>")
             writer.WriteLine("Validation error in: " & _xmlFilePath)
             writer.WriteLine("</th>")
             writer.WriteLine("<tr bgcolor=#6666CC>")
             writer.WriteLine("<td><font color=white><b>Error Message</b>
               </font></td>")
             writer.WriteLine("<td><font color=white><b>Error Location</b>
               </font></td>")
             writer.WriteLine("</tr>")
             writer.Flush()
             writer.Close()
             blnFirst = False 'lay out table only on the first pass
           End If
           writer = new StreamWriter(_logFile, true, Encoding.ASCII)
           writer.WriteLine("<tr bgcolor=D5CCBB>")
           writer.WriteLine("<td width=80%>")
           writer.WriteLine(args.Message)
           writer.WriteLine("</td>")
           If (xmlReader.LineNumber > 0) Then
             writer.WriteLine("<td width=20%>")
             writer.WriteLine("Line: " & xmlReader.LineNumber & 
               " Position: " & xmlReader.LinePosition)
             writer.WriteLine("</td>")
           End If
           writer.WriteLine("</tr>")
         End If
         writer.Flush()
       Catch
       Finally
         'Close writer
         If (NOT writer Is Nothing) Then
           writer.Close()
         End If
       End Try
     End Sub  ' ValidationCallBack()
   End Class  ' ValidatorVB
 
 End Class ' XmlValidateCB1 
Conclusion: In this article we have covered uploading an XML file from your file system to a directory on a web server, saved the file in a specific location, validated the file against a schema loaded on the web server, and created an error log if any type of error was found in the XML file. You have seen the use of a Validating Reader, and the use of Try-Catch-Finally blocks to catch various errors the XML file may contain.

You may download the .aspx and the .aspx.vb files as well as an example XML file and its associated schema (.xsd) file.

Download the files by clicking Here.

 
Please Rate This Article Poor           Excellent
 
 
 
 
 
   © Copyright 2002-2010 DotNetJohn.com LLC
Terms of Use Privacy Policy