2010-06-28 57 views
1

更新:您可以在此结束时运行代码以重新创建并查看我遇到的错误并希望能够解决它!命名空间和反序列化问题

UPDATE2:这不是删除xmlns =“”这是问题......因为您可以从最初的xml字符串中删除它。问题是[XmlType(TypeName =“系统”)]以某种方式导致它被添加...

UPDATE3:原来的问题是在这里,我需要设置TypeName根据什么是在现有的XmlTypeAttribute如果已经在类存在....

xmlAttributes.XmlType = new XmlTypeAttribute 
    { 
     Namespace = "" 
    }; 

我得到以下XML作为字符串从Web服务

<Systems xmlns=""> 
    <System id="1"> 
    <sys_name>ALL</sys_name> 
    </System> 
    <System id="2"> 
    <sys_name>asdfasdf</sys_name> 
    </System> 
    <System id="3"> 
    <sys_name>fasdfasf</sys_name> 
    </System> 
    <System id="4"> 
    <sys_name>asdfasdfasdf</sys_name> 
    </System> 
</Systems> 

然后我执行此,将其转换为一个对象

result = XElement.Parse(xmlResult.OuterXml).Deserialize<AwayRequestSystems>();

奇怪的是,虽然,在反序列化方法,而RemoveAllNamespaces作品,并返回XML没有命名空间

我得到的错误<Systems xmlns=''> was not expected.在捕捉时return (T) serializer.Deserialize(reader);执行!

它为什么这样做? xmlns是GONE !!!

EXECUTABLE CODE! (只是把它放在一个测试项目)

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Xml; 
using System.Xml.Linq; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System.Xml.Serialization; 

namespace DeserializationTest 
{ 
    [TestClass] 
    public class UnitTest1 
    { 
    public TestContext TestContext { get; set; } 

    [TestMethod] 
    public void RemoveXmlnsFromSystems() 
    { 
     var xml = XElement.Parse(@"<Systems xmlns=""""> 
         <System id=""1""> 
         <sys_name>ALL</sys_name> 
         </System> 
         <System id=""2""> 
         <sys_name>ePO</sys_name> 
         </System> 
         <System id=""3""> 
         <sys_name>iEFT</sys_name> 
         </System> 
         <System id=""4""> 
         <sys_name>Away Requests</sys_name> 
         </System> 
         <System id=""5""> 
         <sys_name>RP3</sys_name> 
         </System> 
        </Systems>"); 

     var systems = xml.Deserialize<AwayRequestSystems>(); 
     Assert.IsInstanceOfType(systems, typeof(AwayRequestSystems)); 

     var xmlnsFree = xml.RemoveAllNamespaces(); 
     var str = xmlnsFree.ToString(); 

     Debug.WriteLine(str); 

     Assert.AreNotEqual("Error", xmlnsFree.Name.ToString(), "Serialization Error"); 
     Assert.IsFalse(str.Contains("xmlns"), "Xmlns still exists"); 
    } 
    } 


    [XmlType(TypeName = "Systems")] 
    public class AwayRequestSystems : List<AwayRequestSystem> { } 

    [XmlType(TypeName = "System")] 
    public class AwayRequestSystem 
    { 
    [XmlAttribute("id")] 
    public int ID { get; set; } 

    [XmlElement("sys_name")] 
    public string Name { get; set; } 
    } 

    public static class XmlSerializerFactory 
    { 
    private static Dictionary<Type, XmlSerializer> _serializers = new Dictionary<Type, XmlSerializer>(); 

    public static void ResetCache() 
    { 
     _serializers = new Dictionary<Type, XmlSerializer>(); 
    } 

    public static XmlSerializer GetSerializerFor(Type typeOfT) 
    { 
     if (!_serializers.ContainsKey(typeOfT)) 
     { 
     var xmlAttributes = new XmlAttributes(); 
     var xmlAttributeOverrides = new XmlAttributeOverrides(); 

     Debug.WriteLine(string.Format("XmlSerializerFactory.GetSerializerFor(typeof({0}));", typeOfT)); 

     xmlAttributes.XmlType = new XmlTypeAttribute 
     { 
      Namespace = "" 
     }; 

     xmlAttributes.Xmlns = false; 

     var types = new List<Type> { typeOfT, typeOfT.BaseType }; 

     foreach (var property in typeOfT.GetProperties()) 
     { 
      types.Add(property.PropertyType); 
     } 

     types.RemoveAll(t => t.ToString().StartsWith("System.")); 

     foreach (var type in types) 
     { 
      if (xmlAttributeOverrides[type] == null) 
      xmlAttributeOverrides.Add(type, xmlAttributes); 
     } 

     var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides); 
     //var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides, types.ToArray(), new XmlRootAttribute(), string.Empty); 
     //var newSerializer = new XmlSerializer(typeOfT, string.Empty); 

     _serializers.Add(typeOfT, newSerializer); 
     } 

     return _serializers[typeOfT]; 
    } 
    } 

    public static class XElementExtensions 
    { 
    public static XElement RemoveAllNamespaces(this XElement source) 
    { 
     if (source.HasAttributes) 
     source.Attributes().Where(a => a.Name.LocalName.Equals("xmlns")).Remove(); 

     return source.HasElements 
       ? new XElement(source.Name.LocalName, 
         source.Attributes()/*.Where(a => !a.Name.LocalName.Equals("xmlns"))*/, 
         source.Elements().Select(el => RemoveAllNamespaces(el)) 
       ) 
       : new XElement(source.Name.LocalName) 
       { 
       Value = source.Value 
       }; 
    } 
    } 

    public static class SerializationExtensions 
    { 
    public static XElement Serialize(this object source) 
    { 
     try 
     { 
     var serializer = XmlSerializerFactory.GetSerializerFor(source.GetType()); 
     var xdoc = new XDocument(); 
     using (var writer = xdoc.CreateWriter()) 
     { 
      serializer.Serialize(writer, source, new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") })); 
     } 

     var result = (xdoc.Document != null) ? xdoc.Document.Root : new XElement("Error", "Document Missing"); 

     return result.RemoveAllNamespaces(); 
     } 
     catch (Exception x) 
     { 
     return new XElement("Error", x.ToString()); 
     } 
    } 

    public static T Deserialize<T>(this XElement source) where T : class 
    { 
     //try 
     //{ 
     var serializer = XmlSerializerFactory.GetSerializerFor(typeof(T)); 

     var cleanxml = source.RemoveAllNamespaces(); 
     var reader = cleanxml.CreateReader(); 

     return (T)serializer.Deserialize(reader); 
     //} 
     //catch (Exception x) 
     //{ 
     // return null; 
     //} 
    } 
    } 
} 

回答

1

的问题,因为它原来是因为我用这条线

xmlAttributes.XmlType = new XmlTypeAttribute 
{ 
    Namespace = "" 
}; 

删除命名空间,当失去的TypeName属性我在改变了GetSerializerFor类工厂到以下它现在的工作

public static XmlSerializer GetSerializerFor(Type typeOfT) 
    { 
     if (!_serializers.ContainsKey(typeOfT)) 
     { 
      Debug.WriteLine(string.Format("XmlSerializerFactory.GetSerializerFor(typeof({0}));", typeOfT)); 

      var types = new List<Type> { typeOfT, typeOfT.BaseType }; 

      foreach (var property in typeOfT.GetProperties()) 
      { 
       types.Add(property.PropertyType); 
      } 

      types.RemoveAll(t => t.ToString().StartsWith("System.")); 

      var xmlAttributeOverrides = new XmlAttributeOverrides(); 
      foreach (var type in types) 
      { 
       if (xmlAttributeOverrides[type] != null) 
        continue; 

       var xmlAttributes = new XmlAttributes 
             { 
              XmlType = new XmlTypeAttribute 
                  { 
                   Namespace = "", 
                   TypeName = GetSerializationTypeName(type) 
                  }, 
              Xmlns = false 
             }; 
       xmlAttributeOverrides.Add(type, xmlAttributes); 
      } 

      var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides); 
      //var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides, types.ToArray(), new XmlRootAttribute(), string.Empty); 
      //var newSerializer = new XmlSerializer(typeOfT, string.Empty); 

      _serializers.Add(typeOfT, newSerializer); 
     } 

     return _serializers[typeOfT]; 
    } 

    private static string GetSerializationTypeName(Type type) 
    { 
     var xmlTypeAttribute = TypeDescriptor.GetAttributes(type) 
      .OfType<XmlTypeAttribute>().FirstOrDefault(); 

     var typeName = xmlTypeAttribute.TypeName; 
     return string.IsNullOrEmpty(typeName) ? type.Name : typeName; 
    }