2010-06-22 51 views
14

我有幾個擴展方法來處理我的類的序列化,並且由於它可能是一個耗時的過程,它們每個類創建一次,並通過此方法分發。序列化無xmlns

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

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

     xmlAttributes.Xmlns = false; 
     xmlAttributeOverrides.Add(typeOfT, xmlAttributes); 

     var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides); 
     serializers.Add(typeOfT, newSerializer); 
    } 

    return serializers[typeOfT]; 
} 

這是通過擴展方法.Serialize()

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("", "") })); 
     } 

     return (xdoc.Document != null) ? xdoc.Document.Root : new XElement("Error", "Document Missing"); 
    } 
    catch (Exception x) 
    { 
     return new XElement("Error", x.ToString()); 
    } 
} 

不幸的是,序列化是自動生成的類時,它們具有應用於它們的屬性XmlTypeAttribute(Namespace="http://tempuri.org/")調用。

這會導致非自動生成的對等方的反序列化失敗。

我需要串行完全忽略和不適用的命名空間,但似乎什麼我已經寫在代碼的第一塊不刪除它,我還是落得這樣

<Note> 
    <ID xmlns="http://tempuri.org/">12</ID> 
    <Author xmlns="http://tempuri.org/"> 
    <ID>1234</ID> 
    <Type>Associate</Type> 
    <IsAvailable>false</IsAvailable> 
    </Author> 
    <Created xmlns="http://tempuri.org/">2010-06-22T09:38:01.5024351-05:00</Created> 
    <Text xmlns="http://tempuri.org/">This is an update</Text> 
</Note> 
XML

而不是相同的,減去xmlns="http://tempuri.org/"屬性。

請幫忙,謝謝,這讓我瘋狂!

編輯:

我知道這個問題,而不是如何解決它。

我的課,不僅僅是簡單的類型。

它包含其他類的類型的屬性。這些也是使用XmlTypeAttribute(Namespace = "http://tempuri.org/")屬性自動生成的。所以發生的情況是,當序列化發生時,它會序列化我的類的屬性,它們不會通過我的自定義序列化,因此應用了該屬性並且未覆蓋。

現在我只需要弄清楚如何跳這個箍。任何想法如何?

編輯2:

以下作品連載WITHOUT的xmlns ......但我有在反序列化結束的一個問題,如果只是目前還不確定它的相關或不

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

     System.Diagnostics.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) 
     { 
      xmlAttributeOverrides.Add(type, xmlAttributes); 
     } 

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

     serializers.Add(typeOfT, newSerializer); 
    } 

    return serializers[typeOfT]; 
} 

EDIT3 : 從 How to remove all namespaces from XML with C#?

public static XElement RemoveAllNamespaces(this XElement source) 
{ 
    return !source.HasElements 
       ? new XElement(source.Name.LocalName) 
        { 
         Value = source.Value 
        } 
       : new XElement(source.Name.LocalName, source.Elements().Select(el => RemoveAllNamespaces(el))); 
} 
+1

你最後的解決方案應該已經被命名爲'RemoveAllAttributes' – redtetrahedron 2013-05-31 16:57:18

回答

3

沒問題,結束了使用的解決方案 - 只是傳遞一個空字符串作爲默認命名空間的XML序列化:

XmlSerializer newSerializer = 
    new XmlSerializer(typeOfT, ""); 

不幸的是,沒有簡單的構造函數重載如果你真的需要定義XmlAttributeOverrides和默認命名空間 - 所以要麼你可以跳過XmlAttributeOverrides和使用該構造我所提到的,或者你需要使用定義所有可能參數的參數(包括XmlAttributeOverrides和默認的XML命名空間 - 以及更多)。

+0

這就是我以前其實,也沒有工作,它仍然使用從班上XmlTypeAttribute值。我只是嘗試了以下,它不工作'var newSerializer = new XmlSerializer(typeOfT,xmlAttributeOverrides,new Type [] {},new XmlRootAttribute(),「」);' – CaffGeek 2010-06-22 15:26:52

+0

string.Empty >>>「」 :) – annakata 2010-06-22 15:28:05

+0

@annakata,我也試着用string.Empty替換它。 – CaffGeek 2010-06-22 15:31:32

44

一個工作解決方案,備案!

var ns = new XmlSerializerNamespaces(); 
ns.Add("", ""); 
var serializer = new XmlSerializer(yourType); 
serializer.Serialize(xmlTextWriter, someObject, ns); 
+0

當然是更好的解決方案。奇蹟般有效! – user460762 2013-05-15 19:11:33

+10

爲了記錄,這將刪除'xsi'和'xsd',但它會添加一個新的'xmlns:prefix = ',併爲您的所有標籤添加前綴,前提是您的XmlTypeAttribute在您的指定了名稱空間類。 – redtetrahedron 2013-05-31 16:25:59

+0

這對我來說非常合適,在嘗試了很多不同的事情之後,沒有發生副作用就沒有做這項工作。非常感謝。 – JoeFox 2013-09-20 12:54:34

1
public static byte[] SerializeByteByType(object objectToSerialize, Type type) 
    { 
     XmlWriterSettings xmlSetting = new XmlWriterSettings() 
     { 
      NewLineOnAttributes = false, 
      OmitXmlDeclaration = true, 
      Indent = false, 
      NewLineHandling = NewLineHandling.None, 
      Encoding = Encoding.UTF8, 
      NamespaceHandling = NamespaceHandling.OmitDuplicates 
     }; 

     using (MemoryStream stm = new MemoryStream()) 
     { 
      using (XmlWriter writer = XmlWriter.Create(stm, xmlSetting)) 
      { 
       var xmlAttributes = new XmlAttributes(); 
       var xmlAttributeOverrides = new XmlAttributeOverrides(); 

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

       XmlSerializer serializer = new XmlSerializer(type, xmlAttributeOverrides); 
       //Use the following to serialize without namespaces 
       XmlSerializerNamespaces xmlSrzNamespace = new XmlSerializerNamespaces(); 
       xmlSrzNamespace.Add("", ""); 

       serializer.Serialize(writer, objectToSerialize, xmlSrzNamespace); 
       stm.Flush(); 
       stm.Position = 0; 
      } 

      return stm.ToArray(); 
     } 
    }   
+0

改爲「xmlAttributeOverrides.Add(type,xmlAttributes);」必須是:「var types = type.Assembly.GetTypes()。其中​​(t => string.Equals(t.Namespace,currentType.Namespace,StringComparison.Ordinal)); var xmlAttributeOverrides = new XmlAttributeOverrides(); \t \t \t (類型變量) \t xmlAttributeOverrides.Add(t,xmlAttributes);「 – Mentor 2017-03-29 14:45:35