Search code examples
c#xmlmodel-view-controllerxmlreaderhttppostedfilebase

HttpPostedFileBase to XmlReader.Create()


Is it possible to take a xml file stored in a HttpPostedFileBase property (from MVC form), and create an XMLReader.Create(..,..) object, maintaining line numbers?

The example below uses a hardcoded xml file location..

Ideally XmlReader.Create(MyHttpPostedFileBase, rs);

 public static bool Validate()
    {
        try
        {          
            string XsdPath = @"C:\Projects\Mvc\Xsd\books.xsd";
            string XmlPath = @"C:\Projects\Mvc\Xsd\food.xml"; //replace with my HttpPostedFileBase 

            XmlSchemaSet set = new XmlSchemaSet();
            set.Add(null, XsdPath);

            XmlReaderSettings rs = new XmlReaderSettings();
            rs.Schemas = set;
            rs.ValidationType = ValidationType.Schema;
            rs.ValidationEventHandler += new ValidationEventHandler(rs_ValidationEventHandler);

            using (XmlReader reader = XmlReader.Create(XmlPath, rs))
            {
                while (reader.Read()) ;
            }
        }

static void rs_ValidationEventHandler(object sender, ValidationEventArgs e)
    {                    
       //code
    }

Solution

  • Managed to figure out a solution - hopefully this will help others.

    The issue with creating an XmlDocument from a HttpPostedFileBase Xml upload is that the XmlDocument component does not maintain line numbers.

    The solution was to create a stream from the HttpPostedFileBase and insert that into an XmlReader.Create().

    The code below does two thing: validates that XML is valid, and then validates than XML meets XSD.

    Note: I haven't had time to refactor the code quite yet, but it should be fairly understandable

    public HttpPostedFileBase MyFile { get; set; }
    
    public Stream GetXmlStream()
        {
            using (Stream inputStream = MyFile.InputStream)
            {
                MemoryStream memoryStream = inputStream as MemoryStream;
                memoryStream = new MemoryStream();
                inputStream.CopyTo(memoryStream);
                memoryStream.Position = 0;
                return memoryStream;
            }
        }
    
    public class XmlValidator
    {
        public string Error;
    
        public bool ValidateXml(Stream memoryStream)
        {
            try
            {
                string XsdPath = @"C:\Projects\Mvc\Xsd\books.xsd";
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.Schemas.Add("", XsdPath);
                settings.ValidationType = ValidationType.Schema;
                XmlReader reader = XmlReader.Create(memoryStream, settings);
                XmlDocument document = new XmlDocument();
    
                try
                {
                    document.Load(reader);
                }
                catch (XmlException ex)
                {
                    UploadedFile.Error = String.Format("Line {0}, position {1}: {2}", ex.LineNumber, ex.LinePosition,
                        ex.Message);
                    return false;
                }
    
                ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
                document.Validate(eventHandler);
                reader.Close();
                return true;
            }
            catch (XmlSchemaValidationException ex)
            {
               UploadedFile.Error = String.Format("Line {0}, position {1}: {2}", ex.LineNumber, ex.LinePosition, ex.Message);
            }
            return false;
    
        }
    
        private void ValidationEventHandler(object sender, ValidationEventArgs e)
        {
        }
    
    
    
    
    }