Okay. You can do this with 4 classes and some XmlAttributes on the class properties.
First the xml.. I fixed up the xml to make it consistent and valid xml.
Code:
<?xml version="1.0" encoding="utf-8" ?>
<data>
<drive>
<label>Area 51</label>
<date>12/10/2012</date>
<description>testing site</description>
<status>Valid</status>
<membership>
Username="Jsmith"
Bool="or"
username="MGordon"
</membership>
</drive>
<drive>
<label>Apollo</label>
<date>12/04/2010</date>
<description>fly to the Moon</description>
<status>Terminated</status>
<membership>
Username="DKerr"
bool="and"
Username="Sremi"
bool="or"
Group="ApolloReadOnly"
</membership>
</drive>
<drive>
<label>Deep Impact</label>
<date>12/06/08</date>
<description>Exploring Comet Temple</description>
<status>Achieved</status>
<membership>
<collection>
Username="Gblaine"
Group="SSnype"
group="Wesson"
bool="or"
Computer="Exec-02"
</collection>
</membership>
</drive>
</data>
Next the serialization classes. The Data class is the 'root' class that contains a static Load method. This loads the xml file into a reader, then deserializes it into the Data (and other) class instances.
Code:
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
namespace CG.MultiLevelXml.Serialization
{
public enum Status
{
Achieved = 0,
Terminated = 1,
Valid = 2
}
[XmlType(AnonymousType = true)]
[XmlRoot(ElementName = "data", Namespace = "", IsNullable = false)]
public class Data
{
public static Data Load(string xmlFile)
{
var serializer = new XmlSerializer(typeof (Data));
using( var reader = XmlReader.Create(xmlFile))
{
return (Data) serializer.Deserialize(reader);
}
}
/// <summary>
/// Drive list
/// </summary>
/// <remarks>
/// No te: Use a generic collection here to 'back' the drive array.
/// That way client code won't have to check for Drives == null
/// </remarks>
[XmlElement( "drive" )]
public Drive[] Drives
{
get
{
if( _driveList == null )
{
_driveList = new List<Drive>();
}
return _driveList.ToArray();
}
set
{
if ( _driveList == null )
{
_driveList = new List<Drive>( );
}
if(value != null)
{
_driveList.AddRange(value);
}
}
}
private List<Drive> _driveList = new List<Drive>();
}
public class Drive
{
[XmlElement("label")]
public string Label { get; set; }
[XmlElement( "date" )]
public string Date { get; set; }
[XmlElement("description")]
public string Description { get; set; }
[XmlElement( "status" )]
public Status Status { get; set; }
[XmlElement( "membership" )]
public Membership Membership { get; set; }
/// <summary>
/// Use this property to retrieve the MemberShip or Collection value
/// </summary>
[XmlIgnore]
public string MembershipValue
{
get
{
return IsCollection ? Membership.Collection.Value : Membership.Value;
}
}
/// <summary>
/// Use this property to determine if Membership or Collection
/// </summary>
[XmlIgnore]
public bool IsCollection
{
get
{
return (Membership != null && Membership.Collection != null);
}
}
/// <summary>
/// Override to format an output string
/// </summary>
/// <returns></returns>
public override string ToString( )
{
return String.Format("{0,-15}{1,-15}{2,-30}{3,-12}{4,-14}{5}", Label, Date, Description, Status, IsCollection, MembershipValue);
}
}
public class Membership
{
[XmlText]
public string Value { get; set; }
[XmlElement( "collection", IsNullable = true)]
public Collection Collection { get; set; }
}
public class Collection
{
[XmlText]
public string Value { get; set; }
}
}
Finally, using the class...
Code:
using System;
using CG.MultiLevelXml.Serialization;
namespace CG.MultiLevelXml
{
class Program
{
static void Main( string [ ] args )
{
var data = Data.Load("data.xml");
Console.WriteLine( "{0,-15}{1,-15}{2,-30}{3,-12}{4,-14}{5}\n", "Label", "Date", "Description", "Status", "IsCollection", "MembershipValue" );
foreach(var drive in data.Drives)
{
Console.WriteLine(drive);
}
}
}
}
Output:
Code:
Label Date Description Status IsCollection MembershipValue
Area 51 12/10/2012 testing site Valid False
Username="Jsmith"
Bool="or"
username="MGordon"
Apollo 12/04/2010 fly to the Moon Terminated False
Username="DKerr"
bool="and"
Username="Sremi"
bool="or"
Group="ApolloReadOnly"
Deep Impact 12/06/08 Exploring Comet Temple Achieved True
Username="Gblaine"
Group="SSnype"
group="Wesson"
bool="or"
Computer="Exec-02"
See the attached project solution.
Bookmarks