后代类中没有 xmlns 的 XmlSerializer

问题描述 投票:0回答:1

我需要在 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>
c# xml xmlserializer
1个回答
0
投票

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();
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.