我需要在 XML 中序列化一个包含使用不同具体类实现的 List<> 的类。 我需要一个没有 xmlns 引用的 XML。
这是我的例子:
[Serializable]
public class Root
{
[XmlElement("Tables")]
public List<AbstractTable> Tables { get; set; } = new List<AbstractTable>();
}
[XmlInclude(typeof(TableType1))]
[XmlInclude(typeof(TableType2))]
[Serializable]
public class AbstractTable
{
[XmlAttribute]
public string TableName { get; set; }
}
[Serializable]
public class TableType1 : AbstractTable
{
public TableType1()
{
TableName = "TableType1";
}
[XmlAttribute]
public string ValueA { get; set; }
}
[Serializable]
public class TableType2 : AbstractTable
{
public TableType2()
{
TableName = "TableType2";
}
[XmlAttribute]
public string ValueB { get; set; }
}
class Program
{
static void Main(string[] args)
{
var allegato = new Root();
var tableType1 = new TableType1();
tableType1.ValueA = "AAA";
allegato.Tables.Add(tableType1);
var tableType2 = new TableType2();
tableType2.ValueB = "BBB";
allegato.Tables.Add(tableType2);
var string2Write = SerializeToString(allegato);
File.WriteAllText(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Test.xml"), string2Write);
}
public static string SerializeToString<T>(T value)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(value.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, value, emptyNamespaces);
return stream.ToString();
}
}
}
我从 StackOverflow 获得了 SerializeToString,但仅适用于容器类。
问题是我无法从 XML 中删除 xmlns,这就是我得到的:
<Root>
<Tables p2:type="TableType1" TableName="TableType1" ValueA="AAA" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance" />
<Tables p2:type="TableType2" TableName="TableType2" ValueB="BBB" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance" />
</Root>
将
XmlSerializerNamespaces
与 Empty
命名空间一起使用:您已经为 Root
类执行了此操作。这应该有助于防止根元素中包含任何不需要的名称空间前缀,但它可能无法完全阻止具体类型的 xmlns:p2
(TableType1, TableType2
)。
删除抽象基类上的
XmlInclude
:您可以直接在 XmlInclude
类中使用 AbstractTable
属性来指示可能的类型,而不是在基类 (XmlArrayItem
) 上使用 Root
属性。
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
[Serializable]
public class Root
{
[XmlArray("Tables")]
[XmlArrayItem("TableType1", typeof(TableType1))]
[XmlArrayItem("TableType2", typeof(TableType2))]
public List<AbstractTable> Tables { get; set; } = new List<AbstractTable>();
}
[Serializable]
public abstract class AbstractTable
{
[XmlAttribute]
public string TableName { get; set; }
}
[Serializable]
public class TableType1 : AbstractTable
{
public TableType1()
{
TableName = "TableType1";
}
[XmlAttribute]
public string ValueA { get; set; }
}
[Serializable]
public class TableType2 : AbstractTable
{
public TableType2()
{
TableName = "TableType2";
}
[XmlAttribute]
public string ValueB { get; set; }
}
class Program
{
static void Main(string[] args)
{
var allegato = new Root();
var tableType1 = new TableType1();
tableType1.ValueA = "AAA";
allegato.Tables.Add(tableType1);
var tableType2 = new TableType2();
tableType2.ValueB = "BBB";
allegato.Tables.Add(tableType2);
var string2Write = SerializeToString(allegato);
File.WriteAllText(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Test.xml"), string2Write);
}
public static string SerializeToString<T>(T value)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(value.GetType());
var settings = new XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = true
};
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, value, emptyNamespaces);
return stream.ToString();
}
}
}