2010-06-22 29 views
14

Tôi có một vài phương thức mở rộng xử lý tuần tự các lớp của tôi, và vì nó có thể là một quá trình tốn thời gian, chúng được tạo ra một lần cho mỗi lớp và được đưa ra bằng phương pháp này.Nối tiếp 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.Xmlns = false; 
     xmlAttributeOverrides.Add(typeOfT, xmlAttributes); 

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

    return serializers[typeOfT]; 
} 

này được gọi là theo phương pháp mở rộng .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()); 
    } 
} 

Thật không may, khi Serializing lớp được tự động tạo ra, họ có thuộc tính XmlTypeAttribute(Namespace="http://tempuri.org/") áp dụng đối với họ.

Điều này làm cho quá trình deserialization của các đối tác không được tạo tự động không thành công.

Tôi cần serializer để hoàn toàn bỏ qua và không áp dụng không gian tên, nhưng những gì tôi đã viết trong khối đầu tiên của mã dường như không để xoá bỏ nó, tôi vẫn kết thúc với xml như thế này

<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> 

Thay vì giống nhau, trừ thuộc tính xmlns="http://tempuri.org/".

Xin hãy trợ giúp, cảm ơn, điều này khiến tôi phát điên!

EDIT:

Tôi biết vấn đề, không phải cách khắc phục.

Lớp học của tôi không chỉ đầy các loại đơn giản.

Nó chứa các thuộc tính với các loại lớp khác. Cũng được tạo tự động với thuộc tính XmlTypeAttribute(Namespace = "http://tempuri.org/"). Vì vậy, những gì đang xảy ra, là khi serialization xảy ra, và nó serializes các thuộc tính của lớp học của tôi, họ không đi qua serialization tùy chỉnh của tôi, và do đó, có thuộc tính áp dụng và không ghi đè.

Bây giờ tôi chỉ cần tìm ra cách để nhảy vòng đó. Bất kỳ suy nghĩ như thế nào?

EDIT 2:

Các công trình sau đây để serialize KHÔNG xmlns ... nhưng tôi đang gặp một vấn đề ở đầu deserialization, chỉ cần chưa chắc chắn nếu nó có liên quan hoặc không

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 : Đã kết thúc sử dụng giải pháp từ 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

giải pháp cuối cùng của bạn nên đã có tên 'RemoveAllAttributes' – redtetrahedron

Trả lời

3

Không vấn đề gì - chỉ cần vượt qua một chuỗi rỗng như namespace mặc định để serializer XML:

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

Thật không may, không có nhà xây dựng quá tải dễ dàng nếu bạn thực sự cần phải xác định XmlAttributeOverrides và không gian tên mặc định - do đó, hoặc bạn có thể bỏ qua XmlAttributeOverrides và sử dụng constructor tôi đã đề cập, hoặc bạn cần phải sử dụng một định nghĩa tất cả các tham số có thể (bao gồm XmlAttributeOverrides và các không gian tên XML mặc định - và một vài chi tiết khác).

+0

đó là những gì tôi đã có trước trên thực tế, nó đã không làm việc, người ta vẫn còn sử dụng các giá trị từ XmlTypeAttribute trên lớp. Và tôi chỉ thử những điều sau đây và nó không hoạt động hoặc 'var newSerializer = new XmlSerializer (typeOfT, xmlAttributeOverrides, new Type [] {}, new XmlRootAttribute()," ");' – CaffGeek

+0

string.Empty >>> "" :) – annakata

+0

@annakata, tôi cũng đã thử thay thế bằng string.Empty. – CaffGeek

44

Giải pháp làm việc, để lưu nội dung trò chuyện!

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

Chắc chắn là một giải pháp tốt hơn. Làm việc như một say mê! – user460762

+10

Đối với bản ghi, điều này sẽ loại bỏ 'xsi' và' xsd', nhưng nó sẽ thêm một tiền tố mới 'xmlns: = ' và thêm tiền tố vào tất cả các thẻ của bạn nếu bạn có 'XmlTypeAttribute' với các không gian tên được chỉ định trong các lớp học. – redtetrahedron

+0

Điều này thực sự làm việc hoàn hảo cho tôi, sau khi cố gắng rất nhiều điều khác nhau mà chỉ không làm công việc mà không có tác dụng phụ. Cảm ơn bạn rất nhiều. – JoeFox

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

Thay vào đó "xmlAttributeOverrides.Add (type, xmlAttributes);" phải là: "var types = type.Assembly.GetTypes(). Ở đâu (t => string.Equals (t.Namespace, currentType.Namespace, StringComparison.Ordinal)); var xmlAttributeOverrides = new XmlAttributeOverrides(); \t \t \t foreach (var t in types) \t xmlAttributeOverrides.Thêm (t, xmlAttributes); " – Mentor