views:

1501

answers:

3

I have some WCF methods that are used to transmit information from a server application to a website frontend for use in binding. I'm sending the result as an XElement that is a root of an XML tree containing the data I want to bind against.

I'd like to create some tests that examine the data and ensure it comes across as expected.

My current thinking is this: Every method that returns an XElement tree has a corresponding schema (.XSD) file. This file is included within the assembly that contains my WCF classes as an embedded resource.

Tests call the method on these methods and compares the result against these embedded schemas.

Is this a good idea? If not, what other ways can I use to provide a "guarantee" of what kind of XML a method will return?

If it is, how do you validate an XElement against a schema? And how can I get that schema from the assembly it's embedded in?

+3  A: 

Id say validating xml with a xsd schema is a good idea.

How to validate a XElement with the loaded schema: As you see in this example you need to validate the XDocument first to get populate the "post-schema-validation infoset" (There might be a solution to do this without using the Validate method on the XDOcument but Im yet to find one):

String xsd =
@"<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'&gt;
   <xsd:element name='root'>
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name='child1' minOccurs='1' maxOccurs='1'>
       <xsd:complexType>
        <xsd:sequence>
         <xsd:element name='grandchild1' minOccurs='1' maxOccurs='1'/>
         <xsd:element name='grandchild2' minOccurs='1' maxOccurs='2'/>
        </xsd:sequence>
       </xsd:complexType>
      </xsd:element>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
  </xsd:schema>";
String xml = @"<?xml version='1.0'?>
<root>
    <child1>
        <grandchild1>alpha</grandchild1>
        <grandchild2>beta</grandchild2>
    </child1>
</root>";
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create(new StringReader(xsd)));
XDocument doc = XDocument.Load(XmlReader.Create(new StringReader(xml)));
Boolean errors = false;
doc.Validate(schemas, (sender, e) =>
{
    Console.WriteLine(e.Message);
    errors = true;
}, true);
errors = false;
XElement child = doc.Element("root").Element("child1");
child.Validate(child.GetSchemaInfo().SchemaElement, schemas, (sender, e) =>
{
    Console.WriteLine(e.Message);
    errors = true;
});

How to read the embedded schema from an assembly and add it to the XmlSchemaSet:

Assembly assembly = Assembly.GetExecutingAssembly();
// you can use reflector to get the full namespace of your embedded resource here
Stream stream = assembly.GetManifestResourceStream("AssemblyRootNamespace.Resources.XMLSchema.xsd");
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(null, XmlReader.Create(stream));
element.GetSchemaInfo() returns null.
Will
I dont have the Validate method on the XDocument, this is an extention method from which namespace ?
Alexandre Brisebois
for anyone who is also looking for the name space :using System.Xml.Schema;
Alexandre Brisebois
+2  A: 

If you're doing some light-weight work and XSDs are overkill, consider also possibly strongly typing your XML data. For example, I have a number of classes in a project that derive from XElement. One is ExceptionXElement, another is HttpHeaderXElement, etc. In them, I inherit from XElement and add Parse and TryParse methods that take strings containing XML data to create an instance from. If TryParse() returns false, the string does not conform to the XML data I expect (the root element has the wrong name, missing children elements, etc.).

For example:

public class MyXElement : XElement 
{

    public MyXElement(XElement element)
        : base(element)
    { }

    public static bool TryParse(string xml, out MyXElement myElement)
    {
        XElement xmlAsXElement;

        try
        {
            xmlAsXElement = XElement.Parse(xml);
        }
        catch (XmlException)
        {
            myElement = null;
            return false;
        }

        // Use LINQ to check if xmlAsElement has correct nodes...
    }
Chris
A: 

More info available here: http://msdn.microsoft.com/en-us/library/bb387037.aspx On validating using XSD.

Daud