Document-Centric .NET
by Eric Gropp
|
Pages: 1, 2
OutputAction() #1: An SVG Image
Another familiar benefit of XML interfaces is that an SVG or XHTML presentation is often only a transformation away.
-
To perform the XSLT transform we load our XmlReader into a XPathDocument,
public void OutputAction(XmlReader graphReader) { XPathDocument graphDoc = new XPathDocument(graphReader); -
set up the XslTransform object,
XslTransform xslt = new XslTransform(); xslt.Load("svgGraph.xsl"); -
and write the output to a file. I am using the older .NET 1.0 syntax; In .NET 1.1's the Transform method has changed slightly.
Stream outStream = new FileStream("graph.svg",FileMode.Create); xslt.Transform(graphDoc, null, outStream); outStream.Close(); }
OutputAction() #2: A PNG Bitmap
If some sort of human analysis is required, it's more appropriate to work with a graph than XML. This is how we'll convert our bar graph XML into a PNG image file. The complete source code for this example is in graph2png.zip.
-
The OutputAction method will simply call the static XmlToPng method with the XmlReader. This will write the image onto an output stream.
public void OutputAction(XmlReader graphReader) { Stream outStream = new FileStream("graph.png",FileMode.Create); BarGraphImage.XmlToPng(graphReader,outStream); outStream.Close(); }
-
The static XmlToPng method creates the image by deserializing the XML into an object graph. We'll use the XmlSerializer class to create an instance of the custom BarGraphImage class and then call its WriteImage method to create the PNG image.
public static void XmlToPng(XmlReader reader, Stream output) { // Create a XmlSerializer that will create an // object from the bar graph string ns = "http://example.org/bargraph"; XmlSerializer serializer = new XmlSerializer(typeof(BarGraphImage),ns); // Create a new instance of the BarGraph class from the XML BarGraphImage graphImage = (BarGraphImage)serializer.Deserialize(reader); // Write The Image graphImage.WriteImage(output,ImageFormat.Png); } -
To map the Bar Graph XML to our class, we use attributes (the stuff in the square brackets) to provide hints. For example, the BarGraphImage class will correspond to our top level <BarGraph> element. A useful feature of XmlSerializer is that it will automatically size and populate arrays, so we can leave out helper methods like AddBar(). This can save you a lot of code, especially when instantiating large and deep object graphs.
[XmlRoot("BarGraph")] public class BarGraphImage { public BarGraphImage() {} private Bar[] _bars; [XmlElement("Bar")] public Bar[] Bars { get {return _bars;} set {_bars = value;} } public void WriteImage(Stream output, ImageFormat format) { .... } public static void XmlToPng(XmlReader reader, Stream output) { .... } } public class Bar { public Bar() {} public string Title; public double Value; }
OutputAction() #3: A Network XML Consumer
Perhaps our application is just part of a distributed pipeline or needs to pass the bar graph XML into some sort of content management store. Here we'll pass the bar graph XML on to a protected REST webservice.
-
Create a web request, and supply the Windows credentials in which the application is running,
public void OutputActions(XmlReader graphReader) { string url = "http://somehost/pid/graphRepository.ashx"; WebRequest uploader = WebRequest.Create(url); uploader.Method="POST"; -
Supply the appropriate credentials,
uploader.Credentials = CredentialCache.DefaultCredentials; -
And use the WriteNode() method of XmlWriter to write the contents of the XmlReader to the request stream.
Stream upStream = uploader.GetRequestStream(); XmlWriter upWriter = new XmlTextWriter(upStream,Encoding.UTF8); upWriter.WriteNode(graphReader,true); upWriter.Close(); upStream.Close(); uploader.GetResponse(); }
Conclusion
This architecture is not for everybody. For some, the approach will place unwelcome constraints on W3C XML Schema and class design. Also throughput and security considerations may make it inappropriate for some applications.
However, for applications that live in dynamic environments, you achieve true loose coupling of components with all the flexibility of XML. An XmlReader producing and consuming components of your application can be readily swapped out, improved, or reused by other applications or pipelines. It also reduces the amount of wiring required to tie components together.
More tools are on the way for XML-centric applications in the upcoming versions of .NET and Windows, named Whidbey and Longhorn respectively. .Net brings XQuery Support and the new XmlReader and XmlWriter implementations ObjectReader and ObjectWriter, providing additional support for serializing and deserializing objects. Longhorn's XAML, which uses XML to define windows UI elements, can make interface elements a transformation away from your data or schema XML.