Learning C# by Example

C#, Xml and Xslt

This is a bonus file from snippets of XML related code I wrote about 12 years ago. Some code may be useful to you. Some code will be superceded by more modern methods and frameworks. Happy Hunting!

  1. Read an xml file into a string

    using System;
    using System.IO;
    using System.Xml;
    
    class WriteXMLToString
    {
        //read an xml file and then write to a string 
        //(no error checking)
        public static void Main(string[] args)
        {
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(args[0]);
        StringWriter stringWriter = new StringWriter();
        XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
        xmlTextWriter.Formatting = Formatting.Indented;
        xmlDocument.WriteTo(xmlTextWriter);
        xmlTextWriter.Flush();
        Console.Write(stringWriter.ToString());
        }
    }
    
    
    
  2. How to read an xml file, twist it with an xsl file and then write to a string (no error checking)

    using System;
    using System.IO;
    using System.Xml;
    using System.Xml.Xsl;
    
    class WriteXMLViaXSL
    {
        //read an xml file, twist it with an xsl file and then write to a string (no error checking)
        public static void Main(string[] args)
        {
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(args[0]);
    
        XslTransform xslTransform = new XslTransform();
        xslTransform.Load(args[1]);
    
    
        StringWriter stringWriter = new StringWriter();
        XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
        xmlTextWriter.Formatting = Formatting.Indented;
        xslTransform.Transform(xmlDocument, null, xmlTextWriter);
    
        xmlTextWriter.Flush();
        Console.Write(stringWriter.ToString());
        }
    }
    
  3. Another example reading xml and xslt info from two files and transforming with the more modern XslCompiledTransform

    [Test]
    public void Transform() {
        const string xmlFileNameWithPath = @"C:\workfiles\SwitchBoard\SwitchBoardHandler\Tests\Incidence1.xml";
        const string xslFileNameWithPath = @"C:\workfiles\SwitchBoard\SwitchBoardHandler\xslt\Incidence.xslt";
        XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
        xslCompiledTransform.Load(xslFileNameWithPath);
        StringBuilder stringBuilder = new StringBuilder();
        StringWriter stringWriter = new StringWriter(stringBuilder);
        xslCompiledTransform.Transform(xmlFileNameWithPath, null, stringWriter);
        stringWriter.Close();
        Console.Out.WriteLine("sb.ToString() = {0}", stringBuilder.ToString());
    }
    
  4. Transforming an xml string with an xslt file

     [Test]
    public void Transform() {
        const string xmlFileNameWithPath = @"C:\workfiles\SwitchBoard\SwitchBoardHandler\Tests\Incidence1.xml";
        const string xslFileNameWithPath = @"C:\workfiles\SwitchBoard\SwitchBoardHandler\xslt\Incidence.xslt";
        string xmlString = GetFileAsString(xmlFileNameWithPath);
        XmlTextReader xmlTextReader = new XmlTextReader(new StringReader(xmlString));
        XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
        xslCompiledTransform.Load(xslFileNameWithPath);
        StringBuilder stringBuilder = new StringBuilder();
        StringWriter stringWriter = new StringWriter(stringBuilder);
        xslCompiledTransform.Transform(xmlTextReader, null, stringWriter);
        stringWriter.Close();
        Console.Out.WriteLine("sb.ToString() = {0}", stringBuilder.ToString());
    }
    
  5. How to transform an xml string with an xsl string

    // <summary>
    /// transforms an xml string with an xsl string
    /// </summary>
    /// <param name="xmlString">xml to transform</param>
    /// <param name="XSLStylesheet">stylesheet</param>
    /// <returns>xml transformed</returns>
    public static string TransformXmlStringWithXslString(string xmlString, string XSLStylesheet)
    {
        //process our xml
        XmlTextReader xmlTextReader =
            new XmlTextReader(new StringReader(xmlString));
        XPathDocument xPathDocument = new XPathDocument(xmlTextReader);
    
        //process the xsl
        XmlTextReader xmlTextReaderXslt = new XmlTextReader(new StringReader(XSLStylesheet));
        XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
        xslCompiledTransform.Load(xmlTextReaderXslt);
    
        //handle the output stream
        StringBuilder stringBuilder = new StringBuilder();
        TextWriter textWriter = new StringWriter(stringBuilder);
        
        //do the transform
        xslCompiledTransform.Transform(xPathDocument, null, textWriter);
        return stringBuilder.ToString();
    }
    ...
    [Test]
    public void TransformXmlStringWithXsltString() {
        KoEndPoint koEndPoint = new KoEndPoint("test",null);
        string result = koEndPoint.TransformXmlStringWithXslString("<person name='Francis Bacon' />", "<xsl:stylesheet version='1.0' xmlns:xsl='https://www.w3.org/1999/XSL/Transform'><xsl:template match='/'>Person:<xsl:apply-templates select='*' /></xsl:template><xsl:template match='/person'><xsl:value-of select='@name' /></xsl:template></xsl:stylesheet>");
        Console.Out.WriteLine("result = " + result);
        result.ShouldEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?>Person:Francis Bacon");
    }
    
    
  6. Creates an xml doc programatically and writes to the console and a file

    using System;
    using System.IO;
    using System.Xml;
    
    class CreateXMLDoc
    {
        //creates an xml doc programatically and writes to the console and a file
        public static void Main(string[] args)
        {
        XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.PrependChild(xmlDocument.CreateXmlDeclaration("1.0", "", "yes"));
        XmlElement element = xmlDocument.CreateElement("Book");
        element.SetAttribute("author","Xenophone");
        element.AppendChild(xmlDocument.CreateTextNode("The Persian Expedition"));
        xmlDocument.AppendChild(element);
    
        StringWriter stringWriter = new StringWriter();
        XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
        xmlTextWriter.Formatting = Formatting.Indented;
    
        xmlDocument.WriteTo(xmlTextWriter);
        xmlTextWriter.Flush();
        Console.Write(stringWriter.ToString());
            //get the value of the enviromental variable "TEMP"
        string filename = 
            System.Environment.GetEnvironmentVariable("TEMP")+"\\Book.xml";
        //write to a file in temp directory also
        xmlDocument.Save(filename);
        }
    }
    
  7. Convert XML to an HTML table

    C# has another set of libraries

    using System.Linq;
    using System.Text;
    using System.Xml.Linq;
    
    namespace SwitchBoard.Views.Handler {
        public class HandlerView {
            /// <summary>
            /// takes in well structured xml from something like 
            /// SELECT * FROM mytable AS XML AUTO
            /// where all the elements have identical attribues
            /// and creates an HTML table
            /// </summary>
            /// <param name="xml">collection of xml elements all with the same attributes</param>
            /// <returns>HTML table with class of 'xmlTable'</returns>
            public string ConvertXmlToHtmlTable(string xml) {
                XDocument xDocument = XDocument.Parse("<outer>" + xml + "</outer>");
                XElement root = xDocument.Root;
                if(root == null || root.Elements().Count() == 0) return "Empty";
                var xmlAttributeCollection = root.Elements().First().Attributes();
                StringBuilder html = new StringBuilder("<table class='xmlTable'>\r\n<tr>");
                foreach (var attribute in xmlAttributeCollection)
                {
                    html.Append("<th>"+attribute.Name+"</th>");
                }
                html.Append("</tr>");
                foreach (XElement element in root.Descendants())
                {
                    html.Append("\r\n<tr>");
                    foreach (XAttribute attrib in element.Attributes()) {
                        html.Append("<td>"+attrib.Value+"</td>");
                    }
                    html.Append("</tr>");
                }
                html.Append("</table>");
                return html.ToString();
            }
        }
    }
    
  8. Get an XML document from a web service

    Example of retrieving an XML document from a web service and then applying an XSLT stylesheet on the server side.

        public class ScreenerQuestionsToAsk : System.Web.UI.Page
        {
          private void Page_Load(object sender, System.EventArgs e) {
             GetSurveyDescriptorXMLService service = new
                                               GetSurveyDescriptorXMLService();
             XmlDocument xmlDocument = service.GetAllSurveyDescriptorsAsXMLDoc();
    
             string output = Util.WriteXMLViaXSL(xmlDocument,
                    "w:/mydir/data/Xsl/ScreenerQuestionsToAsk.xsl");
             Response.Write(output);
          }
        }
    
    
  9. How to write XMLNodeList to Console

          public static string ToHTML(XmlNodeList xmlNodeList) {
             StringWriter stringWriter = new StringWriter();
             XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
             xmlTextWriter.Formatting = Formatting.Indented;
             foreach(XmlNode xmlNode in xmlNodeList) {
                xmlNode.WriteTo(xmlTextWriter);
             }
             return stringWriter.ToString();
          }
    
  10. Returning an attribute from an XmlDocument

             string total = xmlDocument.SelectSingleNode("Surveys/Survey[@name='Beer']/cellName[@name='MatureBlueCollarMen']").Attributes.GetNamedItem("total").Value; 
    
    
  11. Using XPath

    The tricky thing about getting the attribute value is using the function 'string()' inside your XPath expression. Otherwise it returns a nodeSetIterator that you have to process.

    using System.Xml;
    using System.Xml.XPath;
    ...
    XPathDocument xPathDocument = new XPathDocument(fileName);
    XPathNavigator xPathNavigator = xPathDocument.CreateNavigator();
    
    string text = (string) xPathNavigator.Evaluate("string(//Survey[@name='"+survey+"']/@URL)");
    
  12. Append a node from text into an existing DOM.

    To import a new node into a DOM, we use the handy 'ImportNode()' method to avoid the 'not in document context' error.

      using System.Xml;
      using System.Xml.XPath;
      ...
      //create initial DOM
      XmlDocument xmlDocument = new XmlDocument(); 
      xmlDocument.LoadXml("<TextDefinitions name='DataSource'></TextDefinitions>");
      ...
      //add new node from xml text
      XmlDocument newXmlDocument = new XmlDocument();
      newXmlDocument.LoadXml("<text lang='en-UK' name='exit'>Goodbye</text>");
      XmlNode newNode = xmlDocument.ImportNode(newXmlDocument.DocumentElement,true);
      xmlDocument.DocumentElement.AppendChild(newNode);
    
  13. How to get a text value from a DOM using XPath.

    Example C# fragment:

     
      using System.Xml;
      using System.Xml.XPath;
      ...
      //create initial DOM
      XmlDocument xmlDocument = new XmlDocument();
        ///   <TextDefinitions>
        ///     <TextDefinition name="DefaultDemographicText">
        ///        <Text lang="en-UK">Thanks for taking our survey.</Text>
        ///        <Text lang="fr-FR">Merci pour prendre notre apercu.</Text>
    
        ///     </TextDefinition>
        ///     <TextDefinition name="ExitText">
        ///        <Text lang="en-UK">Goodbye</Text>
        ///        <Text lang="fr-FR">Au revoir </Text>
    
        ///     </TextDefinition>
        ///   </TextDefinitions>
      xmlDocument.LoadXml("<TextDefinitions>  <TextDefinition name='DefaultDemographicText'>      <Text lang='en-UK'>Thanks for taking our survey.</Text>       <Text lang='fr-FR'>Merci pour prendre notre apercu.</Text>   </TextDefinition>   <TextDefinition name='ExitText'>       <Text lang='en-UK'>Goodbye</Text>       <Text lang='fr-FR'>Au revoir </Text>   </TextDefinition></TextDefinitions>");
      XPathNavigator xPathNavigator = xmlDocument.CreateNavigator();
      ...
    
       private string GetTextFromDOM(string textName,string lang) {
             string query = "string(/TextDefinitions/TextDefinition[@name='"+textName+"']/Text[@lang = '"+lang+"'])";
             string text = (string) xPathNavigator.Evaluate(query);
             if(verbose) { Util.write("GetTextFromDOM(\""+textName+"\", \""+lang+"\"): \""+text+"\""); }
             return text;
          }
       }
    
  14. How to return a single node using XPath expressions with the XmlDocument

        public static Survey GetSurvey(string groupName, string surveyName) {
             XmlDocument xmlSurveys = new XmlDocument();
             xmlSurveys.Load(filename);
             XmlNode xmlNode = (XmlNode) xmlSurveys.SelectNodes("//Survey[@name='"+surveyName+"']").Item(0);
    ...
          }
     
    
  15. How to validate an xml file to a schema programatically

    See also O'Reilly's Indroduction to Schemas, Microsoft's Roadmap for XML Schemas in the .NET Framework and IBM's Basics of using XML Schema.

    /// <summary>
    
    /// validate an xml file to a schema
    /// </summary>
    /// <param name="xmlString">string representation of xml file</param>
    /// <param name="schemaString">string representation of schema</param>
    /// <returns>null if its happy, otherwise a string containing error messages</returns>
    
    public static string ValidateXML(string xmlString, string schemaString) {
    	XmlTextReader xmlTextReader = new XmlTextReader(new StringReader(xmlString));
    	XmlValidatingReader xmlValidatingReader = new XmlValidatingReader(xmlTextReader);
    	xmlValidatingReader.ValidationType = ValidationType.Schema;
    	XmlSchema xmlSchema = new XmlSchema();
    	xmlSchema = XmlSchema.Read(new StringReader(schemaString),null);
    	xmlValidatingReader.Schemas.Add(xmlSchema);
    	Validate validate = new Validate();
    	ValidationEventHandler validationEventHandler = new ValidationEventHandler(validate.Validator);
    	xmlValidatingReader.ValidationEventHandler += validationEventHandler;
    	while (xmlValidatingReader.Read());
    	return validate.errors;
    }
    /// <summary>
    /// tiny class so we can have a ValidationEventHandler and collect the errors
    /// </summary>
    private class Validate {
    	public string errors = null;
    	public  void Validator(object sender, ValidationEventArgs args) {
               errors += args.Message + "\r\n";
    	}
    }
    
  16. Creating a DOM programmatically

    [Test]
    new public void GenerateVenues() { 
    	writeMethodStart(MethodInfo.GetCurrentMethod().ToString());
    	
    	XmlDocument xdoc = new XmlDocument();
    	XmlElement root = xdoc.CreateElement("Schedule");
    	xdoc.AppendChild(root);
    	XmlElement day = xdoc.CreateElement("Day");
    	XmlAttribute date = xdoc.CreateAttribute("date");
    	date.Value = "2004/01/01";
           
    	day.SetAttributeNode(date);
    		XmlAttribute num = xdoc.CreateAttribute("number");
    	num.Value = "5";
    	day.SetAttributeNode(num);
    		root.AppendChild(day);
    		
    	write(To.ToText(xdoc));
    	writeMethodEnd();
    
    }
    
    

    This produces:

    <Schedule>
      <Day date="2004/01/01" number="5" />
    </Schedule> 
    
  17. Example of Serialization using the Xml Formatter

    The binary and SOAP formatters are more useful in most situations.

    using System;
    using System.Xml;
    using System.Xml.Serialization;
    using System.IO;
    
    public class SerializeExample
    {
    	[Serializable]
    	public class Employee {
    		public string name;
    		public int yearOfBirth;
    		public Employee(string name, int yearOfBirth) {
    			this.name = name; this.yearOfBirth = yearOfBirth;
    		}
    		public Employee() {} //needed for serialization
    	}
        public static void Main(string[] args) {
    	Console.Write("starting serialization...");
        FileStream fileStream = File.Create("SerializeExample.xml");
        XmlSerializer xmlSerializer = 
                      new XmlSerializer(typeof(Employee),"Employee");
        xmlSerializer.Serialize(fileStream,new Employee("Achilles",1972));
        fileStream.Close();
        Console.Write("done.");
        }
    }
    
    

    Contents of the file:

    
    <?xml version="1.0"?>
    <Employee xmlns:xsd="https://www.w3.org/2001/XMLSchema" 
      xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" 
      xmlns="Employee">
      <name>Achilles</name>
      <yearOfBirth>1972</yearOfBirth>
    </Employee>
    
  18. Playing with XML
    1. Write a very simple XML fragment the hard way.

       
      static void writeTree(XmlNode xmlElement, int level) {
         String levelDepth = "";
         for(int i=0;i<level;i++) 
         {
            levelDepth += "   ";
         }
         Console.Write("\n{0}<{1}",levelDepth,xmlElement.Name);
         XmlAttributeCollection xmlAttributeCollection = xmlElement.Attributes;
         foreach(XmlAttribute x in xmlAttributeCollection) 
         {
            Console.Write(" {0}='{1}'",x.Name,x.Value);
         }
         Console.Write(">");
         XmlNodeList xmlNodeList = xmlElement.ChildNodes;
         ++level;
         foreach(XmlNode x in xmlNodeList) 
         {
            if(x.NodeType == XmlNodeType.Element) 
            {
               writeTree((XmlNode)x,  level);
            }
            else if(x.NodeType == XmlNodeType.Text) 
            {
               Console.Write("\n{0}   {1}",levelDepth,(x.Value).Trim());
            }
         }
         Console.Write("\n{0}</{1}>",levelDepth,xmlElement.Name);
      }
      
    2. Write a very simple XML fragment the easier way

       
      StringWriter stringWriter = new StringWriter();
      XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
      xmlTextWriter.Formatting = Formatting.Indented;
      xmlDocument.WriteTo(xmlTextWriter); //xmlDocument can be replaced with an XmlNode
      xmlTextWriter.Flush();
      Console.Write(stringWriter.ToString());
      
    3. To write any object or some collections to xml

      Object must have a default constructor.

      public static string SerializeToXmlString(object objectToSerialize) {
          MemoryStream memoryStream = new MemoryStream();
          System.Xml.Serialization.XmlSerializer xmlSerializer = 
              new System.Xml.Serialization.XmlSerializer(objectToSerialize.GetType());
          xmlSerializer.Serialize(memoryStream, objectToSerialize);
          ASCIIEncoding ascii = new ASCIIEncoding();
          return ascii.GetString(memoryStream.ToArray());
      }
      
    4. And this should turn the xml back into an object

      public static object DeSerializeFromXmlString(System.Type typeToDeserialize, string xmlString) {
          byte[] bytes = System.Text.Encoding.UTF8.GetBytes(xmlString);
          MemoryStream memoryStream = new MemoryStream(bytes);
          System.Xml.Serialization.XmlSerializer xmlSerializer = 
              new System.Xml.Serialization.XmlSerializer(typeToDeserialize);
          return xmlSerializer.Deserialize(memoryStream);
      }
      
      

      Example

      [Test]
      public void GetBigList() {
          var textRepository = ObjectFactory.GetInstance<ITextRepository>();
          List<BrandAndCode> brandAndCodeList = textRepository.GetList(...);
          string xml = SerializeToXmlString(brandAndCodeList);
          Console.Out.WriteLine("xml = {0}", xml);
           var brandAndCodeList2 = DeSerializeFromXmlString(typeof (BrandAndCode[]), xml);
      }