使用DataContractSerializer序列化时正在删除已知类型的命名空间

本文关键字:类型 命名空间 删除 DataContractSerializer 序列化 使用 | 更新日期: 2023-09-27 18:26:19

我有一个字典类,它通过自定义WriteXml和ReadXml实现IXmlSerializable。(下面的完整代码)当我使用DataContractSerializer对其进行序列化时,输出包含int、long、string等常见类型的命名空间。如图所示:

<?xml version="1.0" encoding="utf-16"?>
<MyDictionary>
  <DictionaryItem Key="myInteger">
    <Value>
      <int xmlns="http://schemas.microsoft.com/2003/10/Serialization/">4</int>
    </Value>
  </DictionaryItem>
  <DictionaryItem Key="myLong">
    <Value>
      <long xmlns="http://schemas.microsoft.com/2003/10/Serialization/">5</long>
    </Value>
  </DictionaryItem>
  <DictionaryItem Key="myString">
    <Value>
      <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">testing</string>
    </Value>
  </DictionaryItem>
</MyDictionary>

如何将其移除,使其看起来如下图所示?谢谢

<?xml version="1.0" encoding="utf-16"?>
<MyDictionary>
  <DictionaryItem Key="myInteger">
    <Value>
      <int>4</int>
    </Value>
  </DictionaryItem>
  <DictionaryItem Key="myLong">
    <Value>
      <long>5</long>
    </Value>
  </DictionaryItem>
  <DictionaryItem Key="myString">
    <Value>
      <string>testing</string>
    </Value>
  </DictionaryItem>
</MyDictionary>

我用来创建输出的测试代码:

private void button1_Click(object sender, EventArgs e)
    {
        MyDictionary myDictionary = new MyDictionary();
        myDictionary.Add("myInteger", 4);
        Int64 myLong = 5;
        myDictionary.Add("myLong", myLong);
        myDictionary.Add("myString", "testing");
        string outputXml = GetXmlForObject(myDictionary);
        System.IO.File.WriteAllText(@"C:'outputXml.txt", outputXml);
    }
    public static string GetXmlForObject(Object obj)
    {
        try
        {
            DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
            StringBuilder builder = new StringBuilder();
            XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
            xmlWriterSettings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
            xmlWriterSettings.Indent = true;
            using (XmlWriter writer = XmlWriter.Create(builder, xmlWriterSettings))
            {
                serializer.WriteObject(writer, obj);
            }
            return builder.ToString();
        }
        catch (Exception exception)
        {
            return String.Empty;
        }
    }

以下完整代码:

[XmlRoot(Namespace = "")]
public class MyDictionary : Dictionary<String, Object>, IXmlSerializable, ISerializable
{
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        throw new NotImplementedException("The method is not implemented.");
    }
    public void ReadXml(System.Xml.XmlReader reader)
    {
        try
        {
            string key = null;
            object value = null;
            if (reader.IsStartElement() && !reader.IsEmptyElement)
            {
                reader.ReadStartElement();
                while (reader.NodeType != XmlNodeType.EndElement)
                {
                    key = reader.GetAttribute("Key");
                    string typeAttribute = reader.GetAttribute("Null");
                    reader.ReadStartElement("DictionaryItem");
                    if (reader.IsEmptyElement)
                    {
                        this.Add(key, null);
                        reader.ReadStartElement();
                    }
                    else
                    {
                        reader.ReadStartElement("Value");
                        value = GetValueDeserializer(reader.LocalName).ReadObject(reader.ReadSubtree());
                        this.Add(key, value);
                        reader.Skip();  // skipping in case the string is empty or null
                        reader.ReadEndElement();  // Reading end node for Value
                    }
                    reader.ReadEndElement();  // Reading end node for element in the list
                }
                reader.ReadEndElement();
            }
        }
        catch (XmlException e)
        {
            throw new XmlException("ReadXml(XmlReader) reader pointing to invalid element", e);
        }
    }
    private DataContractSerializer GetValueDeserializer(string typeStr)
    {
        Type valueType = GetTypeFromStratusType(typeStr);
        return new DataContractSerializer(valueType);
    }
    public static Type GetTypeFromStratusType(string typeStr)
    {
        Type valueType;
        switch (typeStr)
        {
            case "short":
                valueType = typeof(Int16);
                break;
            case "int":
                valueType = typeof(Int32);
                break;
            case "long":
                valueType = typeof(Int64);
                break;
            case "string":
                valueType = typeof(String);
                break;
            default:
                valueType = typeof(String);
                break;
        }
        return valueType;
    }
    public void WriteXml(System.Xml.XmlWriter writer)
    {
        foreach (KeyValuePair<String, Object> item in this)
        {
            writer.WriteStartElement("DictionaryItem");
            writer.WriteAttributeString("Key", item.Key.ToString());
            if (item.Value != null)
            {
                writer.WriteStartElement("Value");
                DataContractSerializer serializer = new DataContractSerializer(item.Value.GetType());
                serializer.WriteObject(writer, item.Value);
            }
            else
            {
                writer.WriteStartElement("Value");
            }
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    }
}

使用DataContractSerializer序列化时正在删除已知类型的命名空间

您可以创建一个绕过写入命名空间的XmlTextWriter,并将其插入序列化程序。默认情况下。序列化程序使用一个文本编写器,它通过创建XmlDictionaryWriter.CreateTextWriter(…)方法获得该方法,该方法确实写出了名称空间(当然,这是您的问题!)

这个自定义序列化程序根本不会写出名称空间,它应该可以解决您的问题。

public class CustomXmlTextWriter : XmlTextWriter
{    
  public override void WriteStartElement(string prefix, string localName, string ns)
  {
    base.WriteStartElement(null, localName, "");
  }
}