I need to parse a XML file which I get from third party to C# objects. Some of the XML I receive have enumeration values which I want to store in an enum type.
For example, I've got the following xsd of the xml file:
<xsd:simpleType name="brandstof">
<xsd:restriction base="xsd:string">
<!-- Benzine -->
<xsd:enumeration value="B" />
<!-- Diesel -->
<xsd:enumeration value="D" />
<!-- LPG/Gas -->
<xsd:enumeration value="L" />
<!-- LPG G3 -->
<xsd:enumeration value="3" />
<!-- Elektrisch -->
<xsd:enumeration value="E" />
<!-- Hybride -->
<xsd:enumeration value="H" />
<!-- Cryogeen -->
<xsd:enumeration value="C" />
<!-- Overig -->
<xsd:enumeration value="O" />
</xsd:restriction>
</xsd:simpleType>
I want to map this to an enum and I got this far:
public enum Fuel
{
B,
D,
L,
E,
H,
C,
O
}
The problem I have is that the xml can contain a value of 3
which I can't seem to put in the enum type. Is there any solution to put this value in the enum.
I also can get other values with a -
or a /
in them and which I want to put in an enum type.
Anu suggestions are welcome!
Decorate with the XmlEnum
attribute: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlenumattribute.aspx
public enum Fuel
{
[XmlEnum("B")]
Benzine,
[XmlEnum("D")]
Diesel,
[XmlEnum("L")]
LpgGas,
[XmlEnum("3")]
LpgG3,
[XmlEnum("E")]
Elektrisch,
[XmlEnum("H")]
Hybride,
[XmlEnum("C")]
Cryogeen,
[XmlEnum("O")]
Overig
}
You can parse the xml attribute value back to an enum type with:
var value = Enum.Parse(typeof(Fuel), "B");
But I don't think you will get really far with your "special" values ( 3
, a/
etc.). Why don't you define your enum as
enum Fuel
{
Benzine,
Diesel,
// ...
Three,
ASlash,
// ...
}
And write a static method to convert a string to an enum member?
One thing you could look into for implementing such a method would be to add custom attributes to the enum members containing their string representation - if a value doesn't have an exact counterpart in the enumeration, look for a member with the attribute.
Creating such an attribute is easy:
/// <summary>
/// Simple attribute class for storing String Values
/// </summary>
public class StringValueAttribute : Attribute
{
public string Value { get; private set; }
public StringValueAttribute(string value)
{
Value = value;
}
}
And then you can use them in your enum:
enum Fuel
{
[StringValue("B")]
Benzine,
[StringValue("D")]
Diesel,
// ...
[StringValue("3")]
Three,
[StringValue("/")]
Slash,
// ...
}
These two methods will help you parse a string into an enum member of your choice:
/// <summary>
/// Parses the supplied enum and string value to find an associated enum value (case sensitive).
/// </summary>
public static object Parse(Type type, string stringValue)
{
return Parse(type, stringValue, false);
}
/// <summary>
/// Parses the supplied enum and string value to find an associated enum value.
/// </summary>
public static object Parse(Type type, string stringValue, bool ignoreCase)
{
object output = null;
string enumStringValue = null;
if (!type.IsEnum)
{
throw new ArgumentException(String.Format("Supplied type must be an Enum. Type was {0}", type));
}
//Look for our string value associated with fields in this enum
foreach (FieldInfo fi in type.GetFields())
{
//Check for our custom attribute
var attrs = fi.GetCustomAttributes(typeof (StringValueAttribute), false) as StringValueAttribute[];
if (attrs != null && attrs.Length > 0)
{
enumStringValue = attrs[0].Value;
}
//Check for equality then select actual enum value.
if (string.Compare(enumStringValue, stringValue, ignoreCase) == 0)
{
output = Enum.Parse(type, fi.Name);
break;
}
}
return output;
}
And while I'm at it: here is the other way round;)
/// <summary>
/// Gets a string value for a particular enum value.
/// </summary>
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
if (StringValues.ContainsKey(value))
{
output = ((StringValueAttribute) StringValues[value]).Value;
}
else
{
//Look for our 'StringValueAttribute' in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
var attributes = fi.GetCustomAttributes(typeof(StringValueAttribute), false);
if (attributes.Length > 0)
{
var attribute = (StringValueAttribute) attributes[0];
StringValues.Add(value, attribute);
output = attribute.Value;
}
}
return output;
}
Why can't you parse the string
[XmlAttribute("brandstof")]
public string FuelTypeString
{
get { return fuel.ToString(); }
set
{
fuel = (Fuel)System.Enum.Parse(typeof(Fuel), value);
}
}
[XmlIgnore()]
public Fuel FuelType
{
get { return fuel; }
set { fuel = value; }
}
So you really serialize it as a string.
I created a class which handles this:
class EnumCreator
{
public static Type CreateEnum(List<string> AValues)
{
// Get the current application domain for the current thread.
AppDomain currentDomain = AppDomain.CurrentDomain;
// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName aName = new AssemblyName("TempAssembly");
AssemblyBuilder ab = currentDomain.DefineDynamicAssembly(
aName, AssemblyBuilderAccess.RunAndSave);
// Define a dynamic module in "TempAssembly" assembly. For a single-
// module assembly, the module has the same name as the assembly.
ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
// Define a public enumeration with the name "Elevation" and an
// underlying type of Integer.
EnumBuilder eb = mb.DefineEnum("EnumValues", TypeAttributes.Public, typeof(int));
// Define two members, "High" and "Low".
foreach (string v in AValues)
{
eb.DefineLiteral(v, AValues.IndexOf(v));
}
// Create the type and save the assembly.
Type finished = eb.CreateType();
return finished;
}
}
You do have to read the xml file first and put the values in a list, you can do this with the XElement object for example.
//Edit: Like this:
XElement xml = XElement.parse("file.xml");
List<string> enumItems = new List<string>();
foreach(XElement row in xml.Element("xsd:simpleType").Element("xsd:restriction").Elements())
{
enumItems.Add(row.Attribute("value").Value);
}
Type Fuel = EnumCreator.CreatEnum(enumItems);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.