3

I want users to be able to export data as an XML file. Of course I want them to be able to later on import that same XML file however they always could change it or it could be a different XML file.

So I want to validate the XML file to check if it is in the format that I expect. So I guess I would need something like a schema to check just that it has to be through code.

So if I expect

<Root>
 <Something>
    <SomethingElse> </SomethingElse>
 </Something>
</Root>

I don't want some other format to be in the file other then the one I expect.

Also how would I validate fields? Like say I require that there must be some text in between tags. If it is blank the file is not valid.

So how could I do this?

Edit

I decided to use XML serialization so I know it will through an exception if it is the wrong format and ignore stuff that does not work. However I am not sure should I just go through it and C# to validate each of the records or should I try to make an xml schema to do it.

If I would want to do it through an xml schema with xml serialization how would that work? Like Do I first do something like I seen in the responses then de serialize it? Or how would I do it?

chobo2
  • 83,322
  • 195
  • 530
  • 832

5 Answers5

12

Here's a code snippet that you can use to do so:

using (FileStream stream = File.OpenRead(xsdFilepath))
{
    XmlReaderSettings settings = new XmlReaderSettings();

    XmlSchema schema = XmlSchema.Read(stream, OnXsdSyntaxError);
    settings.ValidationType = ValidationType.Schema;
    settings.Schemas.Add(schema);
    settings.ValidationEventHandler += OnXmlSyntaxError;

    using (XmlReader validator = XmlReader.Create(xmlPath, settings))
    {
        // Validate the entire xml file
        while (validator.Read()) ;
    }
}

The OnXmlSyntaxError function will be called when a syntax error occur.

9

There are a few ways to validate XML files. Check out How To Validate an XML Document by Using DTD, XDR, or XSD in Visual C# .NET

Also see Validating an XML against Referenced XSD in C# example

Another good example is Validate XML against XSD using code at runtime in C#

Here is the code from the last post:

public void ValidateXmlDocument(
    XmlReader documentToValidate, string schemaPath)
{
    XmlSchema schema;
    using (var schemaReader = XmlReader.Create(schemaPath))
    {
        schema = XmlSchema.Read(schemaReader, ValidationEventHandler);
    }

    var schemas = new XmlSchemaSet();
    schemas.Add(schema);

    var settings = new XmlReaderSettings();
    settings.ValidationType = ValidationType.Schema;
    settings.Schemas = schemas;
    settings.ValidationFlags =
        XmlSchemaValidationFlags.ProcessIdentityConstraints |
        XmlSchemaValidationFlags.ReportValidationWarnings;
    settings.ValidationEventHandler += ValidationEventHandler;

    using (var validationReader = XmlReader.Create(documentToValidate, 
           settings))
    {
        while (validationReader.Read()) { }
    }
}

private static void ValidationEventHandler(
    object sender, ValidationEventArgs args)
{
    if (args.Severity == XmlSeverityType.Error)
    {
        throw args.Exception;
    }
    Debug.WriteLine(args.Message);
}
Community
  • 1
  • 1
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
2

You can use LINQ to XML: http://msdn.microsoft.com/en-us/library/bb387037.aspx. This page also shows how to do that along with source to dump any invalid nodes: http://blogs.msdn.com/xmlteam/archive/2007/03/03/the-new-linq-to-xml-bridge-classes-to-system-xml.aspx

Ed Power
  • 8,310
  • 3
  • 36
  • 42
0

Validate XML file with Schema in .NET

Josh Stodola
  • 81,538
  • 47
  • 180
  • 227
0

You can use xml serialization in your classes:

[XmlType("Root", Namespace = "http://example.com/Root")]
[XmlRoot(Namespace = "http://example.com/Root.xsd", ElementName = "Root", IsNullable = false)]
public class Root {
  [XmlElement("Something")] 
  public Something Something { get; set; }
}

public class Something {
  [XmlElement("SomethingElse")]
  public SomethingElse SomethingElse { get; set; }
}

public class SomethingElse {
  [XmlText]
  public string Text { get; set; }
}

Serialize it like this:

var serializer = new XmlSerializer(typeof(Root));
serializer.Serialize(outputStrem, myRoot);

You can then test before deserializing, e.g.:

var serializer = new XmlSerializer(typeof(Root));
string xml = @"
  <Root xmlns='http://example.com/Root'>
    <Something>
      <SomethingElse>Yep!</SomethingElse>
    </Something>
  </Root>"; // remember to use the XML namespace!
Debug.Assert(serializer.CanDeserialize(new XmlTextReader(new StringReader(xml))));

And then to deserialize simply:

Root newRoot = (Root)serializer.Deserialize(inputStream);

Your XSD is implicit. It matches your classes. To use richer XSDs, you can venture into Schema Providers.

Jordão
  • 55,340
  • 13
  • 112
  • 144
  • So your using that "xml" string as a a schema provider to check it? But if I wanted to I could make a XSD and do like required fields? – chobo2 Jan 29 '10 at 19:54
  • No, the xml string is not the schema, it is the document that you want to validate. The schema is implicit on the class definitions, and that's what the `XmlSerializer.CanSerialize` uses to validate. You can get the implicit schema from the classes by using the xsd.exe utility. – Jordão Jan 29 '10 at 21:54
  • The xml attributes that control serialization do not cover all the XSD syntax. Unfortunately, I couldn't find an option for an xml attribute to be marked as required with the `XmlAttributeAttribute` class. So having an external XSD and validating an XML against it first would be necessary, if you don't use Schema Providers. – Jordão Jan 29 '10 at 22:05
  • So this is the path to the .xsd file? [XmlRoot(Namespace = "http://example.com/Root.xsd", ElementName = "Root", IsNullable = false)] ? Like I always figured I needed a external XSD but I am still not sure how to tie it with XML serialization? – chobo2 Jan 29 '10 at 22:46
  • There is no XSD file, the attributes in your classes implicitly define it. You can still extract it through the xsd.exe utility. The example.com/Root.xsd is the XML namespace, it can be anything, like a UUID, I've just chosen it poorly with an xsd extension, I'm going to change it. It could point to the real XSD url, but this fact would be opaque to the code; it would only help the external producers of the xml to know the schema beforehand. – Jordão Jan 30 '10 at 04:15