更新:您可以在此结束时运行代码以重新创建并查看我遇到的错误并希望解决它!
UPDATE2:这不是删除 xmlns="" 的问题......因为您可以从初始 xml 字符串中删除它。问题在于 [XmlType(TypeName = "Systems")] 以某种方式导致它被添加......
UPDATE3:原来问题出在这里,我需要根据现有的 XmlTypeAttribute 设置 TypeName,如果它已经存在于类中......
xmlAttributes.XmlType = new XmlTypeAttribute
{
Namespace = ""
};
我从 web 服务获取以下 XML 作为字符串
<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>();
奇怪的是,在 Deserialize 方法中,虽然 RemoveAllNamespaces 工作并返回没有命名空间的 xml
<Systems xmlns=''> was not expected.
执行时我在 catch 中得到错误return (T) serializer.Deserialize(reader);
!
为什么要这样做?xmlns 不见了!!!
可执行代码!(只是把它放在一个测试项目中)
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;
//}
}
}
}