Thursday, April 28, 2011

Using Returned XML with C#

Once you have retrieved data from a web service you will need to do something with it. This HOWTO describes the various built-in methods .NET provides to use XML returned by a web service.
  • Overview
  • Returned Data to a String
  • Using XmlReader
  • Using XmlDocument
  • Using XPathNavigator/XPathDocument
  • Using a DataSet
  • Further Reading

Overview

The .NET Framework provides excellent support for XML. Combined with the databinding support of WinForms and ASP.NET applications you have an easy and powerful set of tools. ASP.NET 2.0 takes databinding another step further by providing the DataSource control which lets you declaratively provide data access to data-bound UI controls.

Returned Data to a String

The simplest way to view the returned data is to get the response stream and put it into a string. This is especially handy for debugging. The following code gets a web page and returns the contents as a string.

C# String Sample


  1. public class StringGet   
  2. {   
  3.     public static string GetPageAsString(Uri address)   
  4.     {   
  5.         string result = "";   
  6.   
  7.         // Create the web request   
  8.         HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;   
  9.   
  10.         // Get response   
  11.         using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)   
  12.         {   
  13.             // Get the response stream   
  14.             StreamReader reader = new StreamReader(response.GetResponseStream());   
  15.   
  16.             // Read the whole contents and return as a string   
  17.             result = reader.ReadToEnd();   
  18.         }   
  19.   
  20.         return result;   
  21.     }   
  22. }   

Using XmlReader

XmlReader provides fast forward-only access to XML data. It also allows you to read data as simple-typed values rather than strings. XmlReader can load an XML document without having to use HttpRequest, though you won't have the same amount of control over the request. If you use HttpRequest, you can just pass the stream returned by the GetResponseStream() method to XmlReader. Fast write-only functions are provided by XmlTextWriter.
With .NET 2.0 you should create XmlReader instances using the System.Xml.XmlReader.Create method. For the sake of compatibility and clarity the next sample uses the .NET 1.1 creation method.

C# XmlReader Sample


  1. using System.Xml;   
  2.   
  3. // Retrieve XML document   
  4. XmlTextReader reader = new XmlTextReader("http://xml.weather.yahoo.com/forecastrss?p=94704");   
  5.   
  6. // Skip non-significant whitespace   
  7. reader.WhitespaceHandling = WhitespaceHandling.Significant;   
  8.   
  9. // Read nodes one at a time   
  10. while (reader.Read())   
  11. {   
  12.     // Print out info on node   
  13.     Console.WriteLine("{0}: {1}", reader.NodeType.ToString(), reader.Name);   
  14. }   

Using XmlDocument

XmlDocument gives more flexibility and is a good choice if you need to navigate or modify the data via the DOM. It also works as a source for the XslTransform class allowing you to perform XSL transformations.

C# XmlDocument Sample


  1. // Create a new XmlDocument   
  2. XmlDocument doc = new XmlDocument();   
  3.   
  4. // Load data   
  5. doc.Load("http://xml.weather.yahoo.com/forecastrss?p=94704");   
  6.   
  7. // Set up namespace manager for XPath   
  8. XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);   
  9. ns.AddNamespace("yweather""http://xml.weather.yahoo.com/ns/rss/1.0");   
  10.   
  11. // Get forecast with XPath   
  12. XmlNodeList nodes = doc.SelectNodes("/rss/channel/item/yweather:forecast", ns);   
  13.   
  14. // You can also get elements based on their tag name and namespace,   
  15. // though this isn't recommended   
  16. //XmlNodeList nodes = doc.GetElementsByTagName("forecast",    
  17. //                          "http://xml.weather.yahoo.com/ns/rss/1.0");   
  18.   
  19. foreach(XmlNode node in nodes)   
  20. {   
  21.     Console.WriteLine("{0}: {1}, {2}F - {3}F",   
  22.                         node.Attributes["day"].InnerText,   
  23.                         node.Attributes["text"].InnerText,   
  24.                         node.Attributes["low"].InnerText,   
  25.                         node.Attributes["high"].InnerText);   
  26. }   

Using XPathNavigator/XPathDocument

XPathDocument provides fast, read-only access to the contents of an XML document using XPath. Its usage is similar to using XPath with XmlDocument.

C# XPathDocument Sample


  1. using System.Xml.XPath;   
  2.   
  3. // Create a new XmlDocument   
  4. XPathDocument doc = new XPathDocument("http://xml.weather.yahoo.com/forecastrss?p=94704");   
  5.   
  6. // Create navigator   
  7. XPathNavigator navigator = doc.CreateNavigator();   
  8.   
  9. // Set up namespace manager for XPath   
  10. XmlNamespaceManager ns = new XmlNamespaceManager(navigator.NameTable);   
  11. ns.AddNamespace("yweather""http://xml.weather.yahoo.com/ns/rss/1.0");   
  12.   
  13. // Get forecast with XPath   
  14. XPathNodeIterator nodes = navigator.Select("/rss/channel/item/yweather:forecast", ns);   
  15.   
  16. while(nodes.MoveNext())   
  17. {   
  18.     XPathNavigator node = nodes.Current;   
  19.   
  20.     Console.WriteLine("{0}: {1}, {2}F - {3}F",   
  21.                         node.GetAttribute("day", ns.DefaultNamespace),   
  22.                         node.GetAttribute("text", ns.DefaultNamespace),   
  23.                         node.GetAttribute("low", ns.DefaultNamespace),   
  24.                         node.GetAttribute("high", ns.DefaultNamespace));   
  25. }   

Using a DataSet

Using a DataSet from the System.Data namespace lets you bind the returned data to controls and also access hierarchical data easily. A dataset can infer the structure automatically from XML, create corresponding tables and relationships between them and populate the tables just by calling ReadXml().

C# DataSet Sample


  1. using System.Data;   
  2.   
  3. public void RunSample()   
  4. {   
  5.     // Create the web request   
  6.     HttpWebRequest request    
  7.         = WebRequest.Create("http://xml.weather.yahoo.com/forecastrss?p=94704"as HttpWebRequest;   
  8.   
  9.     // Get response   
  10.     using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)   
  11.     {   
  12.         // Load data into a dataset   
  13.         DataSet dsWeather = new DataSet();   
  14.         dsWeather.ReadXml(response.GetResponseStream());   
  15.   
  16.         // Print dataset information   
  17.         PrintDataSet(dsWeather);   
  18.     }   
  19. }   
  20.   
  21. public static void PrintDataSet(DataSet ds)   
  22. {   
  23.     // Print out all tables and their columns   
  24.     foreach (DataTable table in ds.Tables)   
  25.     {   
  26.         Console.WriteLine("TABLE '{0}'", table.TableName);   
  27.         Console.WriteLine("Total # of rows: {0}", table.Rows.Count);   
  28.         Console.WriteLine("---------------------------------------------------------------");   
  29.   
  30.         foreach (DataColumn column in table.Columns)   
  31.         {   
  32.             Console.WriteLine("- {0} ({1})", column.ColumnName, column.DataType.ToString());   
  33.         }  // foreach column   
  34.   
  35.         Console.WriteLine(System.Environment.NewLine);   
  36.     }  // foreach table   
  37.   
  38.     // Print out table relations   
  39.     foreach (DataRelation relation in ds.Relations)   
  40.     {   
  41.         Console.WriteLine("RELATION: {0}", relation.RelationName);   
  42.         Console.WriteLine("---------------------------------------------------------------");   
  43.         Console.WriteLine("Parent: {0}", relation.ParentTable.TableName);   
  44.         Console.WriteLine("Child: {0}", relation.ChildTable.TableName);   
  45.         Console.WriteLine(System.Environment.NewLine);   
  46.     }  // foreach relation   
  47. }   

No comments: