I have the following class in C#
public class DynamicFieldParameter
{
[XmlAttribute]
public string ParentName { get; set; }
[XmlAttribute]
public string Label { get; set; }
[XmlAttribute]
public string ParameterName { get; set; }
[XmlAttribute]
public string Value { get; set; }
[XmlAttribute("ParameterValueType")]
public ParameterValueType ValueTypeID { get; set; }
}
Then I have the following Enum,
[Serializable]
public enum ParameterValueType
{
[XmlEnum(Name = "0")]
Conditional,
[XmlEnum(Name = "1")]
Static
}
I am trying to parse the following XML,
<?xml version="1.0" encoding="UTF-8"?>
<DynamicFormExport Version="2">
<DynamicForm>
<DynamicField>
<ListParameters>
<Parameter ParentName="spGetPickListItems" ParameterName="DisplayCode"
Label="Display Code" Value="3" ValueTypeID="1" />
</ListParameters>
</DynamicField>
</DynamicForm>
</DynamicFormExport>
I am using the below code to parse XML,
/// <summary>
/// Iterates through a xml reader and loads a parameter set
/// </summary>
/// <param name="reader">Xml reader. Position is expected to be at the parent node of a parameter collection (e.g. ListParameters)</param>
/// <returns></returns>
private List<DynamicFieldParameter> LoadParametersFromXmlReader(XmlReader reader)
{
List<DynamicFieldParameter> parameters = new List<DynamicFieldParameter>();
if (reader == null)
return parameters;
XmlReader paramReader = reader.ReadSubtree();
paramReader.MoveToContent();
paramReader.Read();
string paramXml = paramReader.ReadOuterXml();
while (!string.IsNullOrEmpty(paramXml))
{
parameters.Add(DynamicFieldParameter.FromXml(paramXml));
paramXml = paramReader.ReadOuterXml();
}
return parameters;
}
What I see in the debugger is that, I get ValueTypeID = Conditional
even though XML I am parsing has ValueTypeID = 1
, I expect my ValueTypeID
to be Static.
What am I doing wrong with the parsing?
Below shows one way to get the desired attribute values by using System.Xml.Serialization.
Create a class (name: HelperXml.cs) for the deserialize method.
HelperXml.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializationTest
{
public class HelperXml
{
public static T DeserializeXMLFileToObject<T>(string xmlFilename)
{
//Usage: Class1 myClass1 = DeserializeXMLFileToObject<Class1>(xmlFilename);
T rObject = default(T);
if (String.IsNullOrEmpty(xmlFilename)) return default(T);
using (System.IO.StreamReader sr = new System.IO.StreamReader(xmlFilename))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
//get data
rObject = (T)serializer.Deserialize(sr);
}
return rObject;
}
}
}
Given the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<DynamicFormExport Version="2">
<DynamicForm>
<DynamicField>
<ListParameters>
<Parameter ParentName="spGetPickListItems" ParameterName="DisplayCode"
Label="Display Code" Value="3" ValueTypeID="1" />
</ListParameters>
</DynamicField>
</DynamicForm>
</DynamicFormExport>
Create classes for each of the following:
As far as naming strategy, in order to keep the classes in the desired order in VS, it can be helpful to do something like the following:
XmlDynamicFormExport
)XmlDynamicFormExportDynamicForm
)XmlDynamicFormExportDynamicFormDynamicField
)XmlDynamicFormExportDynamicFormDynamicFieldListParameters
)XmlDynamicFormExportDynamicFormDynamicFieldListParametersParameter
)Note: The class names I used is the class name above it pre-pended to the class name. (ex: XmlDynamicFormExport + DynamicForm = XmlDynamicFormExportDynamicForm). Although, the names in your XML are somewhat long, so a different naming strategy may be desirable.
XmlDynamicFormExport.cs
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializationTest
{
[XmlRoot(ElementName = "DynamicFormExport", IsNullable = false)]
public class XmlDynamicFormExport
{
[XmlAttribute(AttributeName = "Version")]
public int Version { get; set; }
[XmlElement(ElementName = "DynamicForm")]
public XmlDynamicFormExportDynamicForm DynamicForm = new XmlDynamicFormExportDynamicForm();
}
}
XmlDynamicFormExportDynamicForm.cs
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializationTest
{
public class XmlDynamicFormExportDynamicForm
{
[XmlElement(ElementName = "DynamicField")]
public XmlDynamicFormExportDynamicFormDynamicField DynamicField = new XmlDynamicFormExportDynamicFormDynamicField();
}
}
XmlDynamicFormExportDynamicFormDynamicField.cs
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializationTest
{
public class XmlDynamicFormExportDynamicFormDynamicField
{
[XmlElement(ElementName = "ListParameters")]
public XmlDynamicFormExportDynamicFormDynamicFieldListParameters ListParameters = new XmlDynamicFormExportDynamicFormDynamicFieldListParameters();
}
}
XmlDynamicFormExportDynamicFormDynamicFieldListParameters.cs
Note: Although it wasn't shown in the XML in the OP, it seems like more than 1 parameter could exist, so I used a List in the code below.
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializationTest
{
public class XmlDynamicFormExportDynamicFormDynamicFieldListParameters
{
[XmlElement(ElementName = "Parameter")]
public List<XmlDynamicFormExportDynamicFormDynamicFieldListParametersParameter> Parameter = new List<XmlDynamicFormExportDynamicFormDynamicFieldListParametersParameter>();
}
}
Option 1:
XmlDynamicFormExportDynamicFormDynamicFieldListParametersParameter.cs
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializationTest
{
public enum ParameterValueType
{
[XmlEnum(Name = "0")]
Conditional,
[XmlEnum(Name = "1")]
Static
}
public class XmlDynamicFormExportDynamicFormDynamicFieldListParametersParameter
{
[XmlAttribute(AttributeName = "ParentName")]
public string ParentName { get; set; }
[XmlAttribute(AttributeName = "ParameterName")]
public string ParameterName { get; set; }
[XmlAttribute(AttributeName = "Label")]
public string Label { get; set; }
[XmlAttribute(AttributeName = "Value")]
public int Value { get; set; }
[XmlAttribute(AttributeName = "ValueTypeID")]
public ParameterValueType ValueTypeID { get; set; }
}
}
Usage (Option 1):
string filename = @"C:\Temp\DynamicFormExport.xml";
XmlDynamicFormExport dynamicFormExport = HelperXml.DeserializeXMLFileToObject<XmlDynamicFormExport>(filename);
foreach (var p in dynamicFormExport.DynamicForm.DynamicField.ListParameters.Parameter)
{
System.Diagnostics.Debug.WriteLine("ParentName: " + p.ParameterName + " p.ValueTypeID: " + p.ValueTypeID.ToString());
}
Option 2:
XmlDynamicFormExportDynamicFormDynamicFieldListParametersParameter.cs
using System;
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializationTest
{
[Serializable]
public enum ParameterValueType : int
{
[XmlEnum(Name = "Conditional")]
Conditional = 0,
[XmlEnum(Name = "Static")]
Static = 1
}
[Serializable()]
public class XmlDynamicFormExportDynamicFormDynamicFieldListParametersParameter
{
[XmlAttribute(AttributeName = "ParentName")]
public string ParentName { get; set; }
[XmlAttribute(AttributeName = "ParameterName")]
public string ParameterName { get; set; }
[XmlAttribute(AttributeName = "Label")]
public string Label { get; set; }
[XmlAttribute(AttributeName = "Value")]
public int Value { get; set; }
[XmlAttribute(AttributeName = "ValueTypeID")]
public int ValueTypeID { get; set; }
//this property isn't written to XML, it's only for use in the app
[XmlIgnore]
public ParameterValueType ValueType
{
get { return (ParameterValueType)ValueTypeID; }
set
{
ValueTypeID = (int)value;
}
}
}
}
Usage (Option 2):
string filename = @"C:\Temp\DynamicFormExport.xml";
XmlDynamicFormExport dynamicFormExport = HelperXml.DeserializeXMLFileToObject<XmlDynamicFormExport>(filename);
foreach (var p in dynamicFormExport.DynamicForm.DynamicField.ListParameters.Parameter)
{
System.Diagnostics.Debug.WriteLine("ParentName: " + p.ParameterName + " p.ValueTypeID: " + p.ValueTypeID.ToString() + " p.ValueType: " + p.ValueType.ToString());
}