XmlCsvReader Implementation

 

Chris Lovett
Software Architect, WebData team, Microsoft Corporation

March 2002 (Revised February 2004)

Summary: XmlCsvReader is a sample implementation of an XmlReader that parses tab-delimited .csv files and presents their contents as a stream of XML elements; XmlReader is the Microsoft .NET Framework base class for all managed stream-level XML processing.

Download XmlCsvReaderZip.exe.

Command Line Usage

A command line .exe wrapper is provided for your convenience, or you can code directly to the XmlCsvReader class (the source code included in the above .zip file). The command line looks like this:

XmlCsvReader [-a] [-c] [-root name] [-row name] [customer.csv] 
   [result.xml]

Table 1. Options:

-a Specifies that you want attributes instead of sub-elements.
-c Specifies that the first row contains column names. Without this the columns are named "a1,a2,…an".
-root name Specifies the root element name (default is 'root').
-row name Specifies the row element name (default is 'row').
customer.csv The first file name specifies the .csv input file. If no file names are specified, then it reads from standard input
result.xml The second file name specifies the output xml file. If no second file name is specified, then it writes to standard output

XmlCsvReader Constructor

XmlCsvReader is a subclass of XmlReader so you can use it anywhere you can use the XmlReader, for example in loading XmlDocument objects. The only thing you need to understand beyond the XmlReader API itself (which is documented in the Microsoft .NET Frameworks SDK) are the XmlCsvReader constructors as follows:

public XmlCsvReader( Uri location,
                     XmlNameTable nametable)
public XmlCsvReader( Stream input,
                     Uri baseUri,
                     XmlNameTable nametable)
public XmlCsvReader( TextReader input,
                     Uri baseUri,
                     XmlNameTable nametable)
  • Uri location
    The location of the .csv file. It uses the XmlUrlResolver to resolve this so it could be a file or http location.
  • Stream input
    Alternatively you can load the reader from a stream.
  • TextReader input
    Alternatively you can load the reader from a text reader.
  • Uri baseUri
    When loading from a stream, you also need to provide the baseUri used for resolving external entities.
  • XmlNameTable nametable
    To use while atomizing element names.

XmlCsvReader Code Sample

Test.cs
using System.Xml; 
using Microsoft.Xml;

public class Test {
    
      public static void Main(){
   
   XmlDocument doc = new XmlDocument(); 
   XmlCsvReader reader = new XmlCsvReader(new Uri("file:///C:/My%20Download%20Files/XmlCsvReader/XmlCsvReader/input.csv"), doc.NameTable); 
   reader.FirstRowHasColumnNames = true; 
   reader.RootName = "customers"; 
   reader.RowName  = "customer"; 

   doc.Load(reader); 
   Console.WriteLine(doc.OuterXml);
   doc.Save("output.xml"); 
     }
  
}

Input.csv:
"customer_id","account_num","lname","fname","mi"
1,87462024688,"Nowmer","Sheri","A."
2,87470586299,"Whelply","Derrick","I."
3,87475757600,"Derry","Jeanne",""
4,87500482201,"Spence","Michael","J."
5,87514054179,"Gutierrez","Maya",""
6,87517782449,"Damstra","Robert","F."
7,87521172800,"Kanagaki","Rebecca",""
8,87539744377,"Brunner","Kim","H."
9,87544797658,"Blumberg","Brenda","C."
10,87568712234,"Stanz","Darren","M." 

Output.xml: 
<customers>
  <customer>
    <customer_id>1</customer_id>
    <account_num>87462024688</account_num>
    <lname>Nowmer</lname>
    <fname>Sheri</fname>
    <mi>A.</mi>
  </customer>
  <customer>
    <customer_id>2</customer_id>
    <account_num>87470586299</account_num>
    <lname>Whelply</lname>
    <fname>Derrick</fname>
    <mi>I.</mi>
  </customer>
  <customer>
    <customer_id>3</customer_id>
    <account_num>87475757600</account_num>
    <lname>Derry</lname>
    <fname>Jeanne</fname>
    <mi>
    </mi>
  </customer>
  <customer>
    <customer_id>4</customer_id>
    <account_num>87500482201</account_num>
    <lname>Spence</lname>
    <fname>Michael</fname>
    <mi>J.</mi>
  </customer>
  <customer>
    <customer_id>5</customer_id>
    <account_num>87514054179</account_num>
    <lname>Gutierrez</lname>
    <fname>Maya</fname>
    <mi>
    </mi>
  </customer>
  <customer>
    <customer_id>6</customer_id>
    <account_num>87517782449</account_num>
    <lname>Damstra</lname>
    <fname>Robert</fname>
    <mi>F.</mi>
  </customer>
  <customer>
    <customer_id>7</customer_id>
    <account_num>87521172800</account_num>
    <lname>Kanagaki</lname>
    <fname>Rebecca</fname>
    <mi>
    </mi>
  </customer>
  <customer>
    <customer_id>8</customer_id>
    <account_num>87539744377</account_num>
    <lname>Brunner</lname>
    <fname>Kim</fname>
    <mi>H.</mi>
  </customer>
  <customer>
    <customer_id>9</customer_id>
    <account_num>87544797658</account_num>
    <lname>Blumberg</lname>
    <fname>Brenda</fname>
    <mi>C.</mi>
  </customer>
  <customer>
    <customer_id>10</customer_id>
    <account_num>87568712234</account_num>
    <lname>Stanz</lname>
    <fname>Darren</fname>
    <mi>M.</mi>
  </customer>
</customers>