HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

There has to be a better way of parsing XML in C# than what I'm doing

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
whatthanwaydoingbetterxmlhasparsingthere

Problem

This is the way I'm currently getting data from XML, but it seems to be really inefficient, checking every localname in every iteration. How should I be doing it?

Here is a sample of the XML I am trying to parse, followed by my code.


  
    
      
        2011-04-26 00:00:04
        -104
        10.8
        active
        
        0001234567RN602
        
          
          3
          Suburbia
          21
          Nether
          Easy
          Metropolis
        
        2010-05-05
        
      
    
    9001234567
  
  1.0


I don't have any issues with the maintainability of my code, it's more that it seems like I shouldn't be comparing against so many things at every iteration.

```
public static class DataRetrieval
{

private static XmlNameTable _nt;
private static object _propertyElement;
private static object _unitBalanceElement;
private static object _dailyConsumptionElement;
private static object _statusElement;

static DataRetrieval()
{
_nt = new NameTable();
_propertyElement = _nt.Add("property");
_unitBalanceElement = _nt.Add("unit-balance");
_dailyConsumptionElement = _nt.Add("daily-consumption");
_statusElement = _nt.Add("status");
}

public static bool ParseCustomerData(string raw, out List properties)
{
bool parsedOK = false;
properties = new List();
PropertyDetails property = null;

XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.IgnoreWhitespace = true;
settings.NameTable = _nt;
XmlReader reader = XmlReader.Create(new StringReader(raw), settings);

object localname;

bool continueReading = true;
int dataItemsRead = 0;
const int DataItemsToRead = 3;

try
{

Solution

You could try using XDocument instead.

It would also help to see an example of the xml you're trying to parse in order to properly suggest a refactoring of your code.

EDIT:

You could do this (XDocument + LINQ):

string sXml = @"
                
                  
                    
                      
                        2011-04-26 00:00:04
                        -104
                        10.8
                        active
                        
                        0001234567RN602
                        
                          
                          3
                          Suburbia
                          21
                          Nether
                          Easy
                          Metropolis
                        
                        2010-05-05
                        
                      
                    
                    9001234567
                  
                  1.0
                ";

var xml = XDocument.Parse(sXml);

var r = from x in xml.Descendants("property")
        select new 
        {
            unitBalance = x.Element("unit-balance").Value,
            dailyConsumption = x.Element("daily-consumption").Value,
            status = x.Element("status").Value
        };

this._propertyElement = xml.Descendants("property");
this._unitBalanceElement = r.ElementAt(0).unitBalance;
this._dailyConsumptionElement = r.ElementAt(0).dailyConsumption;
this._statusElement = r.ElementAt(0).status;


Note: I didn't include any error checking, just wanted to show some possibilities.

Code Snippets

string sXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
                <hash>
                  <result>
                    <properties type=""array"">
                      <property>
                        <last-account-review-at>2011-04-26 00:00:04</last-account-review-at>
                        <unit-balance type=""integer"">-104</unit-balance>
                        <daily-consumption type=""decimal"">10.8</daily-consumption>
                        <status>active</status>
                        <end-date></end-date>
                        <icp-number>0001234567RN602</icp-number>
                        <address>
                          <property-name nil=""true""></property-name>
                          <flat-number>3</flat-number>
                          <suburb>Suburbia</suburb>
                          <street-number>21</street-number>
                          <region>Nether</region>
                          <street-name>Easy</street-name>
                          <district>Metropolis</district>
                        </address>
                        <start-date>2010-05-05</start-date>
                        <status-detail nil=""true""></status-detail>
                      </property>
                    </properties>
                    <account-number>9001234567</account-number>
                  </result>
                  <version>1.0</version>
                </hash>";

var xml = XDocument.Parse(sXml);

var r = from x in xml.Descendants("property")
        select new 
        {
            unitBalance = x.Element("unit-balance").Value,
            dailyConsumption = x.Element("daily-consumption").Value,
            status = x.Element("status").Value
        };

this._propertyElement = xml.Descendants("property");
this._unitBalanceElement = r.ElementAt(0).unitBalance;
this._dailyConsumptionElement = r.ElementAt(0).dailyConsumption;
this._statusElement = r.ElementAt(0).status;

Context

StackExchange Code Review Q#2826, answer score: 8

Revisions (0)

No revisions yet.