I have the below classes:
public class MainRequest
{
private Request _dataField;
[XmlElementAttribute(\"Parameters\")]
public Request Parameters
Through experimentation, you'll have to rename Batch
to BatchEntry
(apparently you cannot combine XmlElement
and XmlArrayItem
) and then you can you the XmlArrayItem
attribute with a name of "ParameterEntry".
This will work:
/* No idea why this a 2-d array... It doesn't match your XML */
[XmlArrayItem("ParameterEntry")]
public Field[] BatchEntry //was Batch
It appears that what you’re trying to accomplish isn’t supported natively; there’s no way of applying an XmlElement
attribute to a jagged array. See XmlSerializer bug when serializing collection of collections without root element?
However, what you can do is decompose your Field[][]
jagged array into a simple array of a new type – let’s name it Batch
– which would in turn contain an array of your Field
type. The following code generates the XML you’re after:
public class MainRequest
{
[XmlElementAttribute("Parameters")]
public Request Parameters { get; set; }
}
public class Request
{
[XmlElementAttribute(IsNullable = true)]
public RequestSize RequestSize { get; set; }
[XmlElement("BatchEntry")]
public Batch[] Batches { get; set; }
}
public class RequestSize
{
[XmlAttributeAttribute]
public string Count { get; set; }
[XmlTextAttribute]
public string Value { get; set; }
}
public class Batch
{
[XmlElementAttribute("ParameterEntry")]
public Field[] Fields { get; set; }
}
public class Field
{
[XmlAttributeAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlTextAttribute]
public string Value { get; set; }
}
public static void Main(string[] args)
{
var request = new MainRequest
{
Parameters = new Request
{
RequestSize = new RequestSize
{
Count = "1",
Value = "2",
},
Batches = new Batch[]
{
new Batch
{
Fields = new Field[]
{
new Field { Name = "AAA", Value = "111"},
new Field { Name = "BBB", Value = "222"},
new Field { Name = "CCC", Value = "333"},
}
}
}
}
};
using (var stream = new MemoryStream())
using (var reader = new StreamReader(stream))
{
XmlSerializer serializer = new XmlSerializer(typeof(MainRequest));
serializer.Serialize(stream, request);
stream.Seek(0, SeekOrigin.Begin);
var str = reader.ReadToEnd();
}
}
Generated XML:
<?xml version="1.0"?>
<MainRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Parameters>
<RequestSize Count="1">2</RequestSize>
<BatchEntry>
<ParameterEntry name="AAA">111</ParameterEntry>
<ParameterEntry name="BBB">222</ParameterEntry>
<ParameterEntry name="CCC">333</ParameterEntry>
</BatchEntry>
</Parameters>
</MainRequest>
The advantage of this approach is that it would still work if you define multiple batches. For example:
var request = new MainRequest
{
Parameters = new Request
{
RequestSize = new RequestSize
{
Count = "2",
Value = "5",
},
Batches = new Batch[]
{
new Batch
{
Fields = new Field[]
{
new Field { Name = "AAA", Value = "111"},
new Field { Name = "BBB", Value = "222"},
new Field { Name = "CCC", Value = "333"},
}
},
new Batch
{
Fields = new Field[]
{
new Field { Name = "DDD", Value = "444"},
new Field { Name = "EEE", Value = "555"},
}
}
}
}
};
…would generate:
<?xml version="1.0"?>
<MainRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Parameters>
<RequestSize Count="2">5</RequestSize>
<BatchEntry>
<ParameterEntry name="AAA">111</ParameterEntry>
<ParameterEntry name="BBB">222</ParameterEntry>
<ParameterEntry name="CCC">333</ParameterEntry>
</BatchEntry>
<BatchEntry>
<ParameterEntry name="DDD">444</ParameterEntry>
<ParameterEntry name="EEE">555</ParameterEntry>
</BatchEntry>
</Parameters>
</MainRequest>
Try something like
[XmlIgnore]
public Field[][] Batch
{
get
{
return _field;
}
set
{
_field = value;
}
}
[XmlArrayItemAttribute("ParameterEntry", IsNullable = false)]
public Field[] BatchEntry
{
get
{
List<Field> OneDimFields = new List<Field>();
foreach(Field[] field in _field)
{
OneDimFields.AddRange(field);
}
return OneDimFields.ToArray();
}
}