I have a class for which I need to serialize it in XML. Below is the example:
public class StringArray
{
public List<string> Days { get; set; }
public StringArray()
{
List<string> s = new List<string>();
s.Add("Monday");
s.Add("Tuesday");
s.Add("Wed");
Days = s;
}
}
When I Serialize it in XML format then result is:
<StringArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Days>
<string>Monday</string>
<string>Tuesday</string>
<string>Wed</string>
</Days>
</StringArray>
However, I need result like below:
<StringArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Days>
<Monday />
<Tuesday />
<Wed />
</Days>
</StringArray>
Actually I do not want to show the type of list item.
Note that the set of possible strings is fixed. I also tried using an enum
for this, however the XML shows the enum
type name instead of 'string' which doesn't solve the problem.
Try following :
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(xml);
List<XElement> strings = doc.Descendants("string").ToList();
foreach (XElement xelement in strings)
{
xelement.ReplaceWith(new XElement((string)xelement));
}
}
}
}
Since you have only a fixed set of possible string values, your schema corresponds to an unbounded sequence of choice elements, where the possible element names correspond to the possible string values.
This can be modeled by replacing the string
with some appropriate enum
, then making use of the Choice Element Binding Support support built in to XmlSerializer
, which requires application of XmlChoiceIdentifierAttribute
along with the use of an appropriate serialization surrogate DTO .
First, define an enum
that corresponds to the possible string values:
public enum Day
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
Next, define the following DTO which will be serialized in place of your List<Day>
:
public class DayListDTO
{
[XmlIgnore]
public Day [] Days { get; set; }
[XmlChoiceIdentifier(nameof(DayListDTO.Days))]
[XmlElement(nameof(Day.Monday), typeof(object))]
[XmlElement(nameof(Day.Tuesday), typeof(object))]
[XmlElement(nameof(Day.Wednesday), typeof(object))]
[XmlElement(nameof(Day.Thursday), typeof(object))]
[XmlElement(nameof(Day.Friday), typeof(object))]
[XmlElement(nameof(Day.Saturday), typeof(object))]
[XmlElement(nameof(Day.Sunday), typeof(object))]
public object[] DaysObjects
{
get
{
return Days == null ? null : Enumerable.Repeat(new object(), Days.Length).ToArray();
}
set
{
// Do nothing
}
}
public static implicit operator DayListDTO(List<Day> list)
{
return list == null ? null : new DayListDTO { Days = list.ToArray() };
}
public static implicit operator List<Day>(DayListDTO dayList)
{
return dayList?.Days?.ToList() ?? new List<Day>();
}
}
Finally, make use of the DTO by adding surrogate properties to containing classes as follows:
public class StringArray
{
[XmlIgnore]
public List<Day> Days { get; set; }
[XmlElement("Days")]
public DayListDTO XmlDaysSurrogate { get { return Days; } set { Days = value; } }
}
Which, when serialized, generates the following XML:
<StringArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Days>
<Monday />
<Tuesday />
<Wednesday />
</Days>
</StringArray>
Notes:
To use XmlChoiceIdentifier
correctly with an array, your containing DTO type must have two array members:
DayListDTO.DaysObjects
; DayListDTO.Days
, in 1-1 correspondence with the first array.
Since the elements corresponding to your list of enums contain no contents at all, a dummy array of object
items is returned for the first array.
Using XmlChoiceIdentifier
guarantees that the schema which xsd.exe
auto-generates for your types will correctly indicate an unbounded sequence of correctly-named choice elements. Other solutions such as implementing custom serialization via IXmlSerializable
on some subclass of List<Day>
do not have this advantage.
Working sample fiddle here .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.