So I'm looking to parse an XML file that could look something like this:
<Locations>
<Location Name="California">
<Location Name="Los Angeles">
<Person Name="Harrison Ford"/>
</Location>
</Location>
</Locations>
<People>
<Person Name="Jake Gyllenhaal" Location="Los Angeles"/>
</People>
So I'm building up a list of locations and people. As a business rule a 'person' must be associated with a 'location' but this can be done in one of two ways. Either by listing them as a child of a location element whereby they take on that parent location or by explicitly listing it when listed under the People element. Right now I handle it something like this (without error checking of any kind).
public class Parser
{
public void Parse(XElement xmlRoot)
{
IList<Location> locations = new List<Location>();
IList<Person> people = new List<Person>();
var locationParser = new LocationParser();
locations = locationParser.ParseLocations(xmlRoot.Element("Locations"), people);
var peopleParser = new PeopleParser();
people = peopleParser.ParsePeople(xmlRoot.Element("People"), locations);
// Do stuff with XML read objects.
}
}
public class PeopleParser
{
public IList<Person> ParsePeople(XElement peopleRoot, IList<Location> locations)
{
var xPeople = peopleRoot.Elements("Person");
var people = new List<Person>();
foreach (var person in xPeople)
{
var locationName = person.Attribute("Location").Value;
var location = locations.First(loc => loc.Name.Equals(locationName));
people.Add(this.ParsePerson(person, location));
}
return people;
}
public Person ParsePerson(XElement person, Location location)
{
var personName = person.Attribute("Name").Value;
return new Person(personName, location);
}
}
public class LocationParser
{
PeopleParser peopleParser = new PeopleParser();
public IList<Location> ParseLocations(XElement locationRoot, IList<Person> people)
{
var xLocations = locationRoot.Elements("Location");
var locations = new List<Location>();
foreach (var location in xLocations)
{
locations.Add(this.ParseLocation(location, people));
}
return locations;
}
public Location ParseLocation(XElement xLocation, IList<Person> people)
{
var children = new List<Location>();
foreach (var subLocation in xLocation.Elements("Location"))
{
children.Add(this.ParseLocation(subLocation, people));
}
var newLocation = new Location(xLocation.Attribute("Name").Value, children);
foreach (var xPerson in xLocation.Elements("Person"))
{
people.Add(peopleParser.ParsePerson(xPerson, newLocation));
}
return newLocation;
}
}
}
This code is to me 'ugly' and this is only a simple example of something that gets alot uglier as more dependent XML types are added. Is this about as good as it gets or is there a way this could be rewritten for better separation of concerns?
No comments:
Post a Comment