Support for XSD and Validation of Typed Nodes


Support for XSD and Validation of Typed Nodes

In many of the previous examples, we used explicit casting and accessed nodes through their names as quoted strings. All those casts and quotes are not type safe and cannot be checked at compile time. However, XML document structure is often defined using an XML Schema Definition (XSD). There is a LINQ to XSD project that allows access to XML nodes using a typed and self-describing approach, and it is supported by Microsoft IntelliSense. For instance, the last query you saw in the previous section would be written like the one in Listing 6-35.

Listing 6-35: A LINQ query over XML, based on an XSD typed approach
Image from book

var ordersWithCustomersFromXml =
    from    c in xmlCustomers.customerCollection
    join    o in orders
    on      c.Name equals o.Name
    orderby c.Name
    select  new {
                Name = c.Name,
                City = c.City,
                IdProduct = o.IdProduct,
                Quantity = o.Quantity };
Image from book

As you can see, when using this approach the XML nodes graphs look like any other object graphs-regardless of whether they are made of elements, attributes, or nodes instead of objects. Keep in mind that the LINQ to XSD project is still under construction at the time of writing this book.

XML schema support is also offered through some extension methods defined in the System.Xml.Schema.Extensions class of the System.Xml.Linq assembly. There are just a couple of methods with a few overloads. Those methods are GetSchemaInfo, which extends any XElement or XAttribute instance, and Validate, which extends XDocument, XElement,and XAttribute. The first method (GetSchemaInfo) returns an annotation of type System.Xml.Schema.IXmlSchemaInfo taken from the current node, if present. It retrieves a schema definition mapped to the current node by using LINQ to XML annotations. The Validate method, as you can figure out from its name, validates the source XML node using an XmlSchemaSet containing the schemas to use. Consider the XML schema shown in Listing 6-36.

Listing 6-36: An XML Schema Definition for our sample list of customers
Image from book

<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema id="Customer"
    targetNamespace="http://schemas.devleap.com/Customer"
    elementFormDefault="qualified"
    xmlns="http://schemas.devleap.com/Customer"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:element name="customers">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="customer" minOccurs="0" maxOccurs="unbounded">
          <xsd:complexType>
            <xsd:attribute name="name" type="xsd:string" use="required" />

            <xsd:attribute name="city" type="xsd:string" use="required" />
            <xsd:attribute name="country">
              <xsd:simpleType>
                <xsd:restriction base="xsd:string">
                  <xsd:enumeration value="Italy" />
                  <xsd:enumeration value="USA" />

                </xsd:restriction>
              </xsd:simpleType>
            </xsd:attribute>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>

    </xsd:complexType>
  </xsd:element>
</xsd:schema>
Image from book

You can define an XML graph with this structure, using LINQ to XML as usual, and map the nodes to the previous schema using an XNamespace instance. An example is shown in Listing 6-37.

Listing 6-37: An XML document with the schema of Listing 6-36, built using the LINQ to XML API
Image from book

XNamespace ns = "http://schemas.devleap.com/Customer";
XDocument xmlCustomers = new XDocument(
    new XElement(ns + "customers",
        from   c in customers
        select new XElement(ns + "customer",
                   new XAttribute("city", c.City),
                   new XAttribute("name", c.Name),
                   new XAttribute("country", c.Country))));
Image from book

At this point, you have the xmlCustomers variable that represents an XML Infoset instance related to the schema of Listing 6-36 using its corresponding XML namespace.

In Listing 6-38, you can see how to validate this XDocument using the Validate extension method.

Listing 6-38: XML validation using the Validate extension method
Image from book

static void validateXDocument() {

    // ...

    XmlSchemaSet schemas = new XmlSchemaSet();
    schemas.Add(XmlSchema.Read(new StreamReader(@"..\..\customer.xsd"), null));

    xmlCustomers.Validate(schemas, xmlCustomers_validation);

}

static void xmlCustomers_validation(Object source, ValidationEventArgs args) {
    // In case of validation messages
    Console.WriteLine(args.Message);
}
Image from book

The Validate method internally uses all the standard and common classes and tools of the System.Xml.Schema namespace.


©2008 LINQ - LINQ Labs - Discuss - Terms of Use - Privacy Policy - About LINQ
- Interview Questions - Sharepoint Articles - Interview Questions Resource Library - WPF Articles - MS Knowledgebase Articles - Electronics and Hardware discussions