1

I have an XML file that looks something similar to this:

<root>
    <data label="product data" min="0" max="10">
        <option>
            <id>1</id>
            <name>Name1</name>
        </option>
        <option>
            <id>2</id>
            <name>Name2</name>
        </option>
        <option>
            <id>3</id>
            <name>Name3</name>
        </option>
    </data>
</root>

I need to retreive both data attributes and the option list.

I tried this:

[XmlRoot(ElementName = "root")]
public class Data
{
    // Retreive data attributes
    [XmlElement(ElementName = "data")]
    public Options Attributes { get; set; }

    // Retrieve option list
    [XmlArray("data")]
    [XmlArrayItem("option", Type = typeof(GeneralOptions))]
    public GeneralOptions[] Options { get; set; }
}

Optional classes:

Options

public class Options
{
    [XmlAttribute("label")]
    public string Label{ get; set; }

    [XmlAttribute("min")]
    public string Min{ get; set; }

    [XmlAttribute("max")]
    public string Max{ get; set; }
}

GeneralOptions

public class GeneralOptions
{
    [XmlElement(ElementName = "id")]
    public string Id { get; set; }

    [XmlElement(ElementName = "name")]
    public string Name{ get; set; }
}

But when I try to deserialize the object, it launches the following exception:

The XML element 'data' from namespace '' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.

I imagine the problem is that I'm trying to retreive the same element "twice". But I need to retreive both things. I cannot use the [Attribute] thing because there are several Attributes to retreive, and I need to do this with several XML Elements with the same format and I want to reuse it.

So, how can I retreive both of them?

Sonhja
  • 8,230
  • 20
  • 73
  • 131

2 Answers2

3

You'll need to restructure it slightly:

[XmlRoot("root")]
public class Data
{
    [XmlElement("data")]
    public OptionsData Options { get; set; }
}

public class OptionsData
{
    [XmlAttribute("label")]
    public string Label { get; set; }

    [XmlAttribute("min")]
    public string Min { get; set; }

    [XmlAttribute("max")]
    public string Max { get; set; }

    [XmlElement("option")]
    public List<GeneralOptions> Items { get; } = new List<GeneralOptions>();
}

public class GeneralOptions
{
    [XmlElement("id")]
    public string Id { get; set; }

    [XmlElement("name")]
    public string Name { get; set; }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • (For others who were initially confused, the `Data` class models the `` element, and the `OptionsData` class models the `` element) – canton7 Feb 14 '20 at 12:15
0

I suggest using xmltocsharp or anyother tools to convert the XML to C# Models within seconds... (eliminates all manual mistakes)

As mentioned by @canton7, another easy method is using Visual Studio: Edit -> Paste Special -> Paste XML As Classes

[XmlRoot(ElementName="option")]
public class Option {
    [XmlElement(ElementName="id")]
    public string Id { get; set; }
    [XmlElement(ElementName="name")]
    public string Name { get; set; }
}

[XmlRoot(ElementName="data")]
public class Data {
    [XmlElement(ElementName="option")]
    public List<Option> Option { get; set; }
    [XmlAttribute(AttributeName="label")]
    public string Label { get; set; }
    [XmlAttribute(AttributeName="min")]
    public string Min { get; set; }
    [XmlAttribute(AttributeName="max")]
    public string Max { get; set; }
}

[XmlRoot(ElementName="root")]
public class Root {
    [XmlElement(ElementName="data")]
    public Data Data { get; set; }
}
Krishna Varma
  • 4,238
  • 2
  • 10
  • 25
  • 1
    (Note that there's one built into Visual Studio: Edit -> Paste Special -> Paste XML As Classes. It generates very verbose C#, though) – canton7 Feb 14 '20 at 12:17