Удаление пространств имен для известных типов при сериализации с DataContractSerializer - PullRequest
2 голосов
/ 01 марта 2012

У меня есть словарный класс, который реализует IXmlSerializable с пользовательской реализацией WriteXml и ReadXml. (Полный код ниже). Когда я сериализую его с помощью 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 Ответ

3 голосов
/ 27 апреля 2012

Вы можете создать XmlTextWriter, который обходит запись пространства имен, и подключить его к вашему сериализатору.По умолчанию.Сериализатор использует средство записи текста, которое он получает при создании метода XmlDictionaryWriter.CreateTextWriter (...), который выписывает пространства имен (что, конечно, ваша проблема здесь!)

Этот пользовательский сериализаторне будет выписывать пространства имен вообще, и это должно решить вашу проблему.

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