使用DataContractSerializer进行序列化时删除已知类型的名称空间

时间:2012-03-01 04:33:12

标签: c# serialization namespaces datacontractserializer

我有一个字典类,它使用自定义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();
        }
    }
}

1 个答案:

答案 0 :(得分:3)

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

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

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