Writing XML with the XmlWriter

XmlWriter is an abstract base class that defines an interface for writing XML. The XmlWriter provides a forward-only, read-only, non-cached way of generating XML streams, which helps you to build XML documents that conform to the W3C Extensible Markup Language (XML) 1.0 (Second Edition) (www.w3.org/TR/2000/REC-xml-20001006.html) recommendation and the Namespaces in XML ** recommendation (www.w3.org/TR/REC-xml-names/).

The following list shows that the XmlWriter has methods and properties defined to:

  • Specify whether to support namespaces.
  • Write well-formed XML.
  • Encodes binary bytes as base64 and as binhex, and write out the resulting text.
  • Manage the output, including methods to determine the progress of the output, with the WriteState property.
  • Write multiple documents to one output stream.
  • Flush or close the output.
  • Report the current namespace prefix, xml:lang, or xml:space scope.
  • Write valid names, qualified names, and name tokens.

The following list identifies what the XmlWriter does not check for:

  • Invalid element and attribute name characters.
  • Unicode characters that do not fit the specified encoding. If the Unicode characters do not fit the specified encoding, the XmlWriter does not escape the Unicode characters into character entities.
  • Duplicate attributes.
  • Characters in the DOCTYPE public identifier or system identifier.

Since the XmlWriter does not check these four items, this allows you to produce XML that is not well-formed. If you need to be sure that your element and attribute names contain only valid characters, or has other features listed above, see the topic Customized XML Writer Creation.

A scenario where the XmlWriter could be used is in the reading of legacy data, such as parsing a pipe (|) delimited file of data, and writing the data into an XML format using the XmlTextWriter.

Input

data1|data2|data3|data4|data5

and you would like to transform it to :

Output

<data>
      <item> data1 </item>
      <item> data2 </item>
      <item> data3 </item>
      <item> data4 </item>
      <item> data5 </item>
</data>

A method is created to tokenize the data in the file into individual data tokens. Each call to this function returns one of the data elements. The method takes in a StreamReader.

Public Shared Function NextToken(ByVal stream As StreamReader) As String
    Dim temp As Integer = stream.Read()
    Dim t1 As String = ""
    While temp <> -1 And ChrW(temp) <> "|"
        t1 += ChrW(temp)
        temp = stream.Read()
    End While
    Return t1
End Function 'NextToken
[C#]
public static String NextToken(StreamReader stream)
  {
      int temp = stream.Read();
      String t1 = "";
      while(temp != -1 && temp != (int)'|')
            {
                  t1 += (char)temp;
                  temp = stream.Read();
            }
      return t1;
  }

The code iterates through until there are no data tokens remaining; inserting each token into an XML document. This is done in the Main function, which takes two command line arguments. The first argument is the file to read from, the second is the file to write to. The comments within the code provide a description of the actions taking place.

Imports System
Imports System.IO
Imports System.Xml
Imports Microsoft.VisualBasic.Strings

Namespace TextFiletoXml
    Class TextFiletoXml
        Public Shared file As String
        Public Shared stream As StreamReader
        Public Shared xwriter As XmlTextWriter
        Public Shared val As String

        Public Shared Function NextToken(ByVal stream As StreamReader) As String
            Dim temp As Integer = stream.Read()
            Dim t1 As String = ""
            While temp <> -1 And ChrW(temp) <> "|"
                t1 += ChrW(temp)
                temp = stream.Read()
            End While
            Return t1
        End Function 'NextToken

    Public Overloads Shared Sub Main()
        dim args() As String=System.Environment.GetCommandLineArgs()
        file = args(1)

        'Create a new stream representing the file we are reading from.
        stream = New StreamReader(file, True)

        'Create a new XmlTextWriter.
        xwriter = New XmlTextWriter(args(2), System.Text.Encoding.UTF8)

        'Write the beginning of the document including the 
        'document declaration. Standalone is true. 
        xwriter.WriteStartDocument(True)

        'Write the beginning of the "data" element. This is 
        'the opening tag to our data. 
        xwriter.WriteStartElement("data", "www.alpineskihouse.com")

        'Get the first data element from the file.
        val = NextToken(stream)

        'Create a new element with each data token from the stream.
        While val <> ""
            xwriter.WriteElementString("item", "www.alpineskihouse.com", val)
            val = NextToken(stream)
        End While     
        xwriter.WriteEndElement()  'End the "data" element.
        xwriter.WriteEndDocument() 'End the document

        'Flush the XML document to the underlying stream and
        'close the underlying stream. The data will not be written out 
        'to the stream until either the Flush() method is called or 
        'the Close() method is called.
        xwriter.Close()
    End Sub 'Main
    End Class 'TextFiletoXml
End Namespace 'TextFiletoXml
[C#]
using System;
using System.IO;
using System.Xml;

namespace TextFiletoXml
{

    class TextFiletoXml
    {
        public static String file;
        public static StreamReader stream;
        public static XmlTextWriter xwriter;
        public static String val;
        public static String NextToken(StreamReader stream)
        {
            int temp = stream.Read();
            String t1 = "";
            while(temp != -1 && temp != (int)'|')
            {
                t1 += (char)temp;
                temp = stream.Read();
            }

            return t1;

        }

        public static void Main(string[] args)
        {
            file = args[0];

            //Create a new stream representing the file we are 
            //reading from.
            stream = new StreamReader(file, true);

            //Create a new XmlTextWriter.
           xwriter = new XmlTextWriter(args[1],System.Text.Encoding.UTF8);
            //Write the beginning of the document including the 
            //document declaration. Standalone is true. 

            xwriter.WriteStartDocument(true);

            //Write the beginning of the "data" element. This is 
            //the opening tag to our data 

            xwriter.WriteStartElement("data","www.alpineskihouse.com");

            // Get the first data element from the file.
            val = NextToken(stream);

            //create a new element with each data token from //the stream.
            while(val != "")
            {

               xwriter.WriteElementString("item","www.alpineskihouse.com", val);
                val = NextToken(stream);
            }
            //End the "data" element.
            xwriter.WriteEndElement();

            //End the document
            xwriter.WriteEndDocument();

            //Flush the xml document to the underlying stream and
            //close the underlying stream. The data will not be
            //written out to the stream until either the Flush()
            //method is called or the Close() method is called.
            xwriter.Close();
        }
    }
}

The methods of the XmlWriter and its implementation, XmlTextWriter, write out empty content to the output when a string is used as a parameter, per the W3C rules. That means that for the following methods, if the value null or String.Empty are supplied, the methods write out the text with no data content, and the methods do not throw an exception. Instead, the methods write "". This implementation applies to the WriteProcessingInstruction method when the value null or String.Empty is passed to the text parameter.

  • WriteCData
  • WriteComment
  • WriteProcessingInstruction
  • WriteString

Other methods may throw an exception if passed null or String.Empty.

The XmlWriter has one implementation, the XmlTextWriter. For more information on using XmlTextWriter, see Well-Formed XML Creation with the XmlTextWriter. For more information on XmlWriter methods and properties see XmlWriter Members.

See Also

Well-Formed XML Creation with the XmlTextWriter | XML Output Formatting with XmlTextWriter | Namespace Features within the XmlTextWriter | Customized XML Writer Creation | XmlTextWriter Class | XmlTextWriter Members | XmlWriter Class | XmlWriter Members