In-Depth

XML Advances on B2B Front

Version 2 of the .NET Framework introduces XML-to-relational data mapping, support for XQuery, and typed APIs. Find out why these changes are great news for B2B app development.

Technology Toolbox: C#, XML

Extensible Markup Language (XML) has evolved considerably in its short five-year history. It started out as a simple way to mark up data and relied on seasoned technologies for data validation, such as document type definitions (DTDs). As XML has matured, the World Wide Web Consortium (W3C) has added new technologies—such as XML Schema, Extensible Stylesheet Language Transformations (XSLT), and XPath—to support and enhance its usefulness. XML has grown from being primarily a data-exchange format to one you can also use to generate graphics, PDFs, and even word-processing documents.

Version 1.1 of the .NET Framework supports today's mainstream XML technologies, including DTDs, XML Schema, XSLT, XPath, Simple Object Access Protocol (SOAP) 1.1, Document Object Model (DOM) Level 2, and XML namespaces. Version 2 of the .NET Framework continues to support these technologies (and newer versions where appropriate). It also contains integrated support for SQLXML functionality, simplifies mapping of relational data to XML, and provides an execution and compilation environment for a new query language called XQuery. I'll introduce you to several new XML features in version 2 of the .NET Framework and explain how you can use new XML APIs to work with XML in the applications you'll write in the near future (download the sample code). The code you'll see is based on the alpha Framework release, so class name and namespace changes are certainly possible before the beta appears.

If you've ever developed a business-to-business (B2B) application that moves XML data into a relational database, converts relational data to XML, or exposes data through a Web service, you know how much work it can take to put the initial code infrastructure in place. The currently available approaches to this common problem—such as using XSLT to transform XML into a structure that mirrors database tables, using the XmlTextReader to parse the XML and generate SQL statements, or using SQL Server 2000 XML functionality—generally require a fair amount of development time, and they aren't the most flexible when changes occur in the XML or database schema.

XML APIs in version 2 of the .NET Framework remedy this situation by adding relational-to-XML data mapping. New XML adapters can use these mappings (called XML Views) to generate XML from relational databases and move XML data back into relational database tables. You use XML schemas to define XML Views, which replace custom procedural mappings you write typically using a .NET programming language. XML Views are declarative, so you can decouple applications from the database schema so that schema changes don't require recompilation.

XML Views will provide you with a huge productivity boost, but an even more exciting addition to the version 2 XML APIs is their support for XQuery. XQuery is a query language (similar to Transact-SQL in some regards) that allows you to execute queries against one or more XML data sources. You can employ XQuery to query databases through XML Views, because you can use XML Views to map relational data directly to XML. This includes joining data, performing sorts, ordering results, and more. You can shape the results you generate from executing an XQuery statement as you desire, without resorting to XSLT stylesheets. I'll introduce you to specific XQuery classes later and show you a few basic queries, but I don't have enough space to provide a complete discussion of the XQuery language.

Use Typed APIs
The new XML infrastructure also supports typed APIs that simplify the conversion of XML Schema types to Common Language Runtime (CLR) types, while preventing coding errors in the process. The new typed APIs play an important role in checking XQuery statements at compile time, because XQuery is a typed language. The typed APIs also allow you to copy XML data to CLR objects, manipulate it, then copy it back to the XML data source. Imagine being able to move relational data to a CLR object (and back) simply by using XML schemas. Basic functionality of this sort is available in version 1.1 through tools such as xsd.exe, but version 2 sweetens the deal immensely.

In previous versions of .NET, you typically bind XML to controls, such as the DataGrid, by loading XML into an object that's geared toward relational views of data, such as the DataSet. Version 2 lets you use XPath statements to bind XML data to WinForms and ASP.NET controls. This simplifies data binding by leveraging native XML features rather than requiring you to load XML into objects that provide relational data views.

Now that you've read about a few of the new XML features, I'll shift focus to some of the new classes in version 2 that make these features possible. Microsoft has gone to a great deal of effort to make version 2 of the Framework backward-compatible. Classes you're accustomed to using in .NET to parse, edit, and transform XML data—such as XmlTextReader, XmlDocument, and XslTransform—are still available in version 2 and have been enhanced to improve performance in some cases.

A few of the version 2 classes mirror functionality in previous versions of the Framework and add new capabilities. For example, the XPathDocument class in version 1.1 provides a read-only cache of XML data; you typically use it to transform XML with the XslTransform class, or create an instance of the abstract XPathNavigator class to walk the XML data structure. The XPathDocument2 class in version 2 (slated to be renamed back to XPathDocument in the beta) allows you to read and edit XML data. I'll show you later how to accomplish this.

Several classes in version 2, such as XQueryProcessor, provide features unavailable in previous Framework versions. XQueryProcessor resides in the System.Xml.Query namespace within the System.Data.SqlXml.dll assembly (at least in the alpha release). It allows you to compile and execute XQuery statements so you can query one or more XML documents.

An XQuery statement looks a lot like an XPath statement with additional keywords and brackets. This simple XQuery statement queries a document called books.xml, which contains a list of books and related publication data (see Listing 1). The query locates the titles of all books with a publisher of "Sams Publishing" and a publication date more recent than 2000:

<books>
   {
   for    $b in doc("BooksDoc")/books/book
   where $b/publisher = "Sams 
      Publishing" 
   and $b/@year > 2000
   return
      <book year="{ $b/@year }">
         { $b/title }
      </book>
   }
</books>

The preceding query is based on the W3C XQuery use cases. You can capture the query results directly without writing any XSLT template code.

This is the result when the previous XQuery statement executes:

<books>
   <book year="2001">
      XML for ASP.NET Developers
   </book>
   <book year="2001">
      ASP.NET: Tips, Tutorials, and 
      Code
   </book>
</books>

Join Multiple XML Documents
XQuery can also "join" multiple XML documents. Suppose you have an authors.xml document containing author data:

<authors>
   <author first="Dan" last="Wahlin">
      <bio>
         Provides training and 
         consulting services. Writes 
         articles and books.</bio>
      <books>
         <book>Professional Windows 
         DNA</book>
         <book>XML for ASP.NET 
         Developers</book>
         <book>ASP.NET: Tips, 
         Tutorials, and Code</book>
      </books>
   </author>
</authors>

This code joins the books.xml document in Listing 1 with authors.xml:

<bios>
{
   for $b in 
      document("BooksDoc")/books/book,
      $a in 
         document(
         "AuthorsDoc")/authors/author
   where $b/author/last = $a/@last
   and $b/author/first = $a/@first
   and $b/publisher = "Sams Publishing"
   return
      <bio first="{$a/@first}" 
         last="{$a/@last}">
         { $a/bio }
      </bio>
}
</bios>

Bios for Sams Publishing authors appear in the results after you execute the preceding query. The C# code that executes this query relies on the XQueryProcessor class and another class named XmlDataSourceResolver (see Listing 2). Notice that the code in Listing 2 compiles the XQuery statement, creates aliases specified in the query (BooksDoc and AuthorsDoc), and uses the XmlDataSourceResolver's Add() method to associate the aliases with a physical XML document. The code then executes the query by calling the XQueryProcessor's Execute() method.

You also can use the XQuery functionality to perform XSLT transformations more efficiently than you can with version 1.1's XslTransform class. These improved XSLT transformations rely on a new class named XsltProcessor (also in the System.Xml.Query namespace) that uses XQuery internally:

XsltProcessor xslt = 
   new XsltProcessor();
//Compile stylesheet
xslt.Compile("XSLT/Books.xslt");
StringWriter writer = 
   new StringWriter();
//Perform transformation
xslt.Execute("Xml/books.xml", 
   new XmlUrlResolver(), null, writer);
string results = writer.ToString();

You can also use XQuery to query relational databases by combining XML Views with a new class, named XmlAdapter, that enhances ADO.NET's XML integration capabilities. XmlAdapter is quite useful when the target XML structure doesn't mirror the database table schema structure. The XmlAdapter class can also employ mapping schemas to fill an XPathDocument2 class, much as you can use DataAdapters to fill DataSets.

Once you fill the XPathDocument2 class, you can use XSLT to transform it, use XQuery to query it, or use XML APIs to inspect it (see Figure 1). You can feed updates to the data in an XPathDocument2 object back to the XmlAdapter, which can then update the original relational data store through its Update() method. This functionality is a welcome addition to applications that perform B2B integration.

You use a mapping schema to represent the shape you want for the XML data returned from querying a relational database (see Listing 3). You also must create another type of schema that describes the database table structure, in order to stream the relational data to XML (see Listing 4). Finally, you must create a third document—the XML View—that acts as the glue between the XML schema and the database schema (see Listing 5). The XQueryProcessor uses the XML View to query relational data (see Listing 6).

You associate the XML View mapping document with the XQueryProcessor through its XmlViewSchemaDictionary property. Notice that the XQuery statement in Listing 6 references the XML View mapping file (which has an alias of CustomersOrders):

map:view('CustomersOrders')/
   Customer[@id='ALFKI']

After the code in Listing 6 creates an instance of XQueryProcessor, it creates a connection to the database, then creates a new instance of an XmlAdapter. Calling the XmlAdapter's Fill() method then fills an XPathDocument2 object with data. After all these steps are complete, the XML data in the XPathDocument2 object is saved to a string for display.

You also can update the XPathDocument2 object (unlike the XPathDocument in version 1.1 of the Framework). You use a new class named XPathEditor—currently located in the System.Xml namespace—to do this. XPathEditor has methods, such as CreateAttributeString(), CreateFirstChild(), and CreateNextSibling(), you can use to manipulate the data. You can use the XPathEditor along with the XPathDocument2 and XmlAdapter classes to persist changed XML data back to the database. This code performs edits and persists the changes back to the database through the XmlAdapter:

//Create XPathEditor from XPathDocument2
XPathEditor editor = 
   doc.CreateXPathEditor();
//Perform edits to XPathDocument2
editor.MoveToFirstChild ();
editor.CreateFirstChild (
   "<Order orderID='4002' " +
   "date='2003-10-14' id='ALFKI'/>");
//Update db through XmlAdapter's 
//Update() method
xmlAdapter.Update(doc,map); 

I've only scratched the surface when it comes to new XML features in .NET version 2, but you can see that significant enhancements allow you to integrate XML and relational data more easily. XQuery lets you query different types of data stores using a standard syntax that's easy to learn with a little practice. These features and others will enable your B2B applications to share data more easily and adapt to change much more quickly.

Featured

comments powered by Disqus

Subscribe on YouTube