c# - 使用 DataContractSerializer 序列化时删除已知类型的命名空间

标签 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();
        }
    }
}

最佳答案

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

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

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

关于c# - 使用 DataContractSerializer 序列化时删除已知类型的命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9510654/

相关文章:

.net - OpemXML 命名空间

c# - 使用 Installutil 安装服务

java - 如何在 Java 中存储不可序列化对象的引用? (安卓)

c# - 在 .NET 中使用 DataSet.WriteXml 时的自定义日期时间格式

json - Microsoft Azure dll 在 .NET 4.0 中引发异常

c++ - 跨命名空间和不同 .H 文件的友元类

javascript - 在 JavaScript 中创建命名空间

c# - Environment.SpecialFolder.CommonApplicationData 返回 Program Files/App 文件夹

c# - 从 BitmapSource 复制到 WriteableBitmap

c# - Visual Studio 2013 和 Update 2(间歇性构建错误)