-1

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?

tRuEsAtM
  • 3,517
  • 6
  • 43
  • 83
  • Shouldnt variable name be "ID" instead of "Id"? – Naveen Aug 21 '21 at 18:14
  • `[XmlAttribute("ParameterValueType")]` ... `Parameter ValueTypeID="1"` – Ian Kemp Aug 21 '21 at 18:25
  • @Naveen Updated, it's actually ID; I was playing around and mistakenly put Id. Still not getting the desired output, though. – tRuEsAtM Aug 21 '21 at 18:48
  • @IanKemp, Could you please elaborate on Code? – tRuEsAtM Aug 21 '21 at 18:50
  • [How do you use XMLSerialize for Enum typed properties in c#?](https://stackoverflow.com/questions/2306299/how-do-you-use-xmlserialize-for-enum-typed-properties-in-c/2306335) – Luuk Aug 21 '21 at 18:55
  • What is `FromXml`? – Tu deschizi eu inchid Aug 21 '21 at 19:27
  • @Luuk I tried it decorating with ``` [Serializable] public enum ParameterValueType { [XmlEnum(Name = "0")] Conditional, [XmlEnum(Name = "1")] Static }``` but, it didn't work. – tRuEsAtM Aug 21 '21 at 21:02
  • @user9938 FromXml is a method that takes string XML, and root as the parameter and returns the type. For eg. ```public static DynamicFieldParameter FromXml(string xml, string root = "Parameter")``` – tRuEsAtM Aug 21 '21 at 21:03

1 Answers1

2

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:

  • DynamicFormExport
  • DynamicForm
  • DynamicField
  • ListParameters
  • Parameter

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:

  • DynamicFormExport (name: XmlDynamicFormExport)
  • DynamicForm (name: XmlDynamicFormExportDynamicForm)
  • DynamicField (name: XmlDynamicFormExportDynamicFormDynamicField)
  • ListParameters (name: XmlDynamicFormExportDynamicFormDynamicFieldListParameters)
  • Parameter (name: 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());
}
Tu deschizi eu inchid
  • 4,117
  • 3
  • 13
  • 24