Assuming your input XML actually IS valid XML, this is the pattern I use for this type of thing.
Your example XML isn't valid because Player
is both self closing, and has an explicit closing tag. I've adjusted it to my best guess of what it should look like.
If that really is the XML you have to deal with, XmlDocument.LoadXml
will throw an error. You will need to find some other way to deal with the malformed data, perhaps pre-processing the data to remove the /
on the Player
element so it is no longer self closing.
The basic pattern is that there is a class for each element in the XML. Each class has a static function FromXml
that accepts an XmlElement
for the matching element in the XML. FromXML
is responsible for reading, parsing, and populating its properties from attributes. Child elements are processed by calling FromXml
on their associated classes.
class Program
{
static void Main(string[] args)
{
string xml =
@"<Baseball>
<Player playerID=""123"" playerName=""John Smith"" playerBats=""Right"">
<position positionID=""1b"" positionCode=""abc"" counter=""3""/>
<position positionID=""2b"" positionCode=""def"" counter=""2""/>
</Player>
</Baseball>";
var document = new XmlDocument();
document.LoadXml(xml);
var players = new List<Player>();
foreach (XmlElement baseballElement in document.SelectNodes("Baseball"))
{
foreach (XmlElement playerElement in baseballElement.SelectNodes("Player"))
{
players.Add(Player.FromXml(playerElement));
}
}
Console.ReadLine();
}
}
public class Player
{
public static Player FromXml(XmlElement PlayerElement)
{
var player = new Player();
player.PlayerId = int.Parse(PlayerElement.GetAttribute("playerID"));
player.PlayerName = PlayerElement.GetAttribute("playerName");
player.PlayerBats = PlayerElement.GetAttribute("playerBats");
foreach (XmlElement positionElement in PlayerElement.SelectNodes("position"))
{
player.Positions.Add(Position.FromXml(positionElement));
}
return player;
}
public int PlayerId { get; set; }
public string PlayerName { get; set; }
public string PlayerBats { get; set; }
private List<Position> _positions = new List<Position>();
public List<Position> Positions
{
get { return _positions; }
}
}
public class Position
{
public static Position FromXml(XmlElement positionElement)
{
var position = new Position();
position.PositionId = positionElement.GetAttribute("positionID");
position.PositionCode = positionElement.GetAttribute("positionCode");
position.Counter = int.Parse(positionElement.GetAttribute("counter"));
return position;
}
public string PositionId { get; set; }
public string PositionCode { get; set; }
public int Counter { get; set; }
}
This will create a list of Player
each of which contains a list of Position
, all populated from the XML.
I also haven't done any kind of error checking on the input XML. If any attributes are missing or in the wrong format, it will throw an error.