Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading Xml with XmlReader in C#

Tags:

c#

xml

xmlreader

I'm trying to read the following Xml document as fast as I can and let additional classes manage the reading of each sub block.

<ApplicationPool>     <Accounts>         <Account>             <NameOfKin></NameOfKin>             <StatementsAvailable>                 <Statement></Statement>             </StatementsAvailable>         </Account>     </Accounts> </ApplicationPool> 

However, I'm trying to use the XmlReader object to read each Account and subsequently the "StatementsAvailable". Do you suggest using XmlReader.Read and check each element and handle it?

I've thought of seperating my classes to handle each node properly. So theres an AccountBase class that accepts a XmlReader instance that reads the NameOfKin and several other properties about the account. Then I was wanting to interate through the Statements and let another class fill itself out about the Statement (and subsequently add it to an IList).

Thus far I have the "per class" part done by doing XmlReader.ReadElementString() but I can't workout how to tell the pointer to move to the StatementsAvailable element and let me iterate through them and let another class read each of those proeprties.

Sounds easy!

like image 525
Gloria Huang Avatar asked Mar 14 '10 09:03

Gloria Huang


People also ask

What is the best way to read XML in C#?

The XmlReader class in C# provides an efficient way to access XML data. XmlReader. Read() method reads the first node of the XML file and then reads the whole file using a while loop.

Which class in C# would you use to connect to an XML file and read it?

This article shows you how to use the XmlTextReader class to read XML from a URL. The streamed information can come from kinds of sources, such as a byte stream from a server, a file, or a TextReader class.

How do I read an XML document?

XML files are encoded in plaintext, so you can open them in any text editor and be able to clearly read it. Right-click the XML file and select "Open With." This will display a list of programs to open the file in. Select "Notepad" (Windows) or "TextEdit" (Mac).

What's the difference between XmlDocument and XmlReader?

XmlDocument is very easy to use. Its only real drawback is that it loads the whole XML document into memory to process. Its seductively simple to use. XmlReader is a stream based reader so will keep your process memory utilization generally flatter but is more difficult to use.


1 Answers

My experience of XmlReader is that it's very easy to accidentally read too much. I know you've said you want to read it as quickly as possible, but have you tried using a DOM model instead? I've found that LINQ to XML makes XML work much much easier.

If your document is particularly huge, you can combine XmlReader and LINQ to XML by creating an XElement from an XmlReader for each of your "outer" elements in a streaming manner: this lets you do most of the conversion work in LINQ to XML, but still only need a small portion of the document in memory at any one time. Here's some sample code (adapted slightly from this blog post):

static IEnumerable<XElement> SimpleStreamAxis(string inputUrl,                                               string elementName) {   using (XmlReader reader = XmlReader.Create(inputUrl))   {     reader.MoveToContent();     while (reader.Read())     {       if (reader.NodeType == XmlNodeType.Element)       {         if (reader.Name == elementName)         {           XElement el = XNode.ReadFrom(reader) as XElement;           if (el != null)           {             yield return el;           }         }       }     }   } } 

I've used this to convert the StackOverflow user data (which is enormous) into another format before - it works very well.

EDIT from radarbob, reformatted by Jon - although it's not quite clear which "read too far" problem is being referred to...

This should simplify the nesting and take care of the "a read too far" problem.

using (XmlReader reader = XmlReader.Create(inputUrl)) {     reader.ReadStartElement("theRootElement");      while (reader.Name == "TheNodeIWant")     {         XElement el = (XElement) XNode.ReadFrom(reader);     }      reader.ReadEndElement(); } 

This takes care of "a read too far" problem because it implements the classic while loop pattern:

initial read; (while "we're not at the end") {     do stuff;     read; } 
like image 106
Jon Skeet Avatar answered Sep 17 '22 22:09

Jon Skeet