使用XmlSerializer序列化含anyType元素的string数组时丢失xsi:type属性的原因咨询
xsi:type Attribute is Missing The issue boils down to how XmlSerializer handles type information by default: it only includes the xsi:type attribute when the actual runtime type of an element doesn't match the declared base type for that element.
In your case, you're using a string[] to map to the <anyType> elements. Since string is the exact type XmlSerializer expects for the array items (and it's compatible with the generic anyType), it sees no need to explicitly add the xsi:type="xsd:string" attribute—it assumes the receiver will know the type from the schema or the property declaration.
Here are a few straightforward solutions to force the xsi:type attribute to appear:
1. Switch to object[] (Simplest Approach)
Change your property to use object[] instead of string[]. When you store string values in an object array, XmlSerializer recognizes that the runtime type (string) is different from the declared type (object), so it will automatically add the xsi:type attribute:
[XmlArrayItem("anyType", IsNullable = true)] public object[] FieldValues { get; set; }
When populating the array, just cast your strings to objects:
FieldValues = new[] { "val1", "val2", "val3" }.Cast<object>().ToArray();
This will produce the XML you expect, with each <anyType> element carrying the xsi:type="xsd:string" attribute.
2. Use XmlAttributeOverrides to Force Type Output
If you need to keep using string[], you can override the serializer's behavior to treat each array item as an object (instead of string), which triggers the xsi:type attribute:
var overrides = new XmlAttributeOverrides(); var arrayItemAttr = new XmlArrayItemAttribute("anyType", typeof(string)) { IsNullable = true, Type = typeof(object) // Tell serializer to treat items as object }; overrides.Add(typeof(YourTargetClass), "FieldValues", arrayItemAttr); // Use this custom serializer instead of the default one var serializer = new XmlSerializer(typeof(YourTargetClass), overrides);
3. Implement IXmlSerializable (Full Control)
For complete control over the XML structure, implement the IXmlSerializable interface to manually write the xsi:type attribute:
public class YourTargetClass : IXmlSerializable { public string[] FieldValues { get; set; } public XmlSchema GetSchema() => null; public void ReadXml(XmlReader reader) { // Handle deserialization (parse the <anyType> elements) reader.ReadStartElement("FieldValues"); var values = new List<string>(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.Name == "anyType") { values.Add(reader.ReadElementContentAsString()); } else { reader.Skip(); } } reader.ReadEndElement(); FieldValues = values.ToArray(); } public void WriteXml(XmlWriter writer) { writer.WriteStartElement("FieldValues"); if (FieldValues != null) { foreach (var val in FieldValues) { writer.WriteStartElement("anyType"); // Explicitly write the xsi:type attribute writer.WriteAttributeString( "xsi", "type", "http://www.w3.org/2001/XMLSchema-instance", "xsd:string"); if (val != null) { writer.WriteString(val); } writer.WriteEndElement(); } } writer.WriteEndElement(); } }
This approach lets you dictate exactly how the XML is structured, ensuring the xsi:type attribute is included every time.
内容的提问来源于stack exchange,提问作者Amichai Simcha

