4

I have the following class.

public class ConfigurationItem
{
    public String Type { get; set; }
    public String Value { get; set; }
}

This code performs the serialization.

static void Main(string[] args)
{
    List<ConfigurationItem> cis = new List<ConfigurationItem>();
    cis.Add(new ConfigurationItem() { Type = "Car", Value = "Car Value" });
    cis.Add(new ConfigurationItem() { Type = "Bike", Value = "Bike Value" });

    System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(cis.GetType());
    x.Serialize(Console.Out, cis);
}

The actual output is below.

<?xml version="1.0" encoding="IBM437"?>
<ArrayOfConfigurationItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <ConfigurationItem>
        <Type>Car</Type>
        <Value>Car Value</Value>
    </ConfigurationItem>
    <ConfigurationItem>
        <Type>Bike</Type>
        <Value>Bike Value</Value>        
    </ConfigurationItem>
</ArrayOfConfigurationItem>

I would like to produce the following XML.

<?xml version="1.0" encoding="IBM437"?>
<ArrayOfConfigurationItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <ConfigurationItem>
        <Type>Car</Type>
        <Value Label="Car Label">Car Value</Value>
    </ConfigurationItem>
    <ConfigurationItem>
        <Type>Bike</Type>
        <Value Label="Bike Label">Bike Value</Value>        
    </ConfigurationItem>
</ArrayOfConfigurationItem>

I have following type to Label mapping table available

Dictionary<String, String> ValueLabels = new Dictionary<string, string>()
{
    {"Car","Car Label"},
    {"Bike","Bike Label"}
};

I can't touch the ConfigurationItem class. Is it possible to use System.Xml.Serialization.XmlAttributeOverrides or something similar?

Edit 1 I have an ugly solution that I'm using now. I'm using normal serialization and adding data to the XmlDocument manually.

static void Main(string[] args)
{
    List<ConfigurationItem> cis = new List<ConfigurationItem>();
    cis.Add(new ConfigurationItem(){Type = "Car", Value = "Car Value"});
    cis.Add(new ConfigurationItem(){Type = "Bike", Value = "Bike Value"});

    Dictionary<String, String> valueLabels = new Dictionary<string, string>()
    {
        {"Car","Car Label"},
        {"Bike","Bike Label"}
    };

    var detailDocument = new System.Xml.XmlDocument();
    var nav = detailDocument.CreateNavigator();

    if (nav != null)
    {
        using (System.Xml.XmlWriter w = nav.AppendChild())
        {
            var ser = new System.Xml.Serialization.XmlSerializer(cis.GetType());
            ser.Serialize(w, cis);
        }
    }
    var nodeList = detailDocument.DocumentElement.SelectNodes("//ConfigurationItem");
    foreach (System.Xml.XmlNode node in nodeList)
    {
        String type = ((System.Xml.XmlElement)node.SelectNodes("Type")[0]).InnerText;
        ((System.Xml.XmlElement)node.SelectNodes("Value")[0]).SetAttribute("Label", valueLabels[type]);
    }

    System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(Console.Out);
    writer.Formatting = System.Xml.Formatting.Indented;
    detailDocument.WriteTo(writer);            

    Console.ReadLine();
}

Still looking for better solution...

2

2 Answers 2

3

If you want to output an attribute, you'll need a property which will be serialized as the attribute. Try the following:

public class ConfigurationItem
{
    public String Type { get; set; }
    public String Value { get; set; }
    [XmlAttribute("Label")]
    public string Label
    {
        get {return Value;}
        set {Value = value;}
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer. Only problem is that I can't touch the ConfigurationItem class and add extra properties in it.
In that case, you're pretty much out of luck, unless you create yourself a separate class, just for serialization.
0

It's been a long time since the issue. But I hope it will be a solution for those who have similar problem.

For the "Value" xml node;

[XmlRoot("Value")]
public class ValueNode
{
    public ValueNode()
    {
    }

    public ValueNode(string label, string value)
    {
        Label = label;
        Value = value;
    }

    [XmlAttribute]
    public string Label { get; set; }

    [XmlText]
    public string Value { get; set; }
}

For the "ConfigurationItem" xml node;

[XmlRoot("ConfigurationItem")]
public class ConfigurationItemWrapper
{
    private static readonly Dictionary<string, string> ValueLabels = new Dictionary<string, string>()
    {
        {"Car","Car Label"},
        {"Bike","Bike Label"}
    };

    public ConfigurationItemWrapper()
    {
    }

    public ConfigurationItemWrapper(ConfigurationItem item)
    {
        if (item is null)
        {
            throw new ArgumentNullException(nameof(item));
        }

        Type = item.Type;
        Value = new ValueNode(
                ValueLabels.ContainsKey(item.Type)
            ? ValueLabels[item.Type]
            : null,
                item.Value);
    }

    public string Type { get; set; }
    public ValueNode Value { get; set; }

    public static explicit operator ConfigurationItem(ConfigurationItemWrapper item)
    {
        return (item is null)
            ? null
            : new ConfigurationItem() { Type = item.Type, Value = item.Value?.Value };
    }

    public static explicit operator ConfigurationItemWrapper(ConfigurationItem item)
    {
        return (item is null)
            ? null
            : new ConfigurationItemWrapper(item);
    }
}

To serialize the "List<ConfigurationItem>" list in the expected format;

[XmlRoot("ArrayOfConfigurationItem")]
public class ConfigurationItemListWrapper
{
    public ConfigurationItemListWrapper()
    {
        Items = new List<ConfigurationItemWrapper>();
    }

    public ConfigurationItemListWrapper(IEnumerable<ConfigurationItem> items)
    {
        Items = new List<ConfigurationItemWrapper>(items.Select(x => (ConfigurationItemWrapper)x));
    }

    [XmlElement("ConfigurationItem")]
    public List<ConfigurationItemWrapper> Items { get; set; }
}

Use of;

static void Main(string[] args)
{
    List<ConfigurationItem> cis = new List<ConfigurationItem>();
    cis.Add(new ConfigurationItem() { Type = "Car", Value = "Car Value" });
    cis.Add(new ConfigurationItem() { Type = "Bike", Value = "Bike Value" });

    System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(ConfigurationItemListWrapper));
    x.Serialize(Console.Out, new ConfigurationItemListWrapper(cis));

    Console.ReadLine();
}

The expected console output will be as follows.

<?xml version="1.0" encoding="IBM437"?>
<ArrayOfConfigurationItem xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ConfigurationItem>
    <Type>Car</Type>
    <Value Label="Car Label">Car Value</Value>
  </ConfigurationItem>
  <ConfigurationItem>
    <Type>Bike</Type>
    <Value Label="Bike Label">Bike Value</Value>
  </ConfigurationItem>
</ArrayOfConfigurationItem>

I hope it will be a solution for those who have similar problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.