2013-08-08 3 views
3

Следующий пример дает мне "[One xmlns = ''] не ожидалось." Исключениедесериализовать с разными именами корневых элементов

public abstract class BaseClass{ } 

[XmlRoot("One")] 
public class ChildOne : BaseClass {} 

[XmlRoot("Two")] 
public class ChildTwo : BaseClass { } 

class Program 
{ 
    private static void Main(string[] args) 
    { 
     var ser = new XmlSerializer(typeof (BaseClass), new Type[] {typeof (ChildOne), typeof (ChildTwo)}); 
     var obj1 = ser.Deserialize(new StringReader(@"<?xml version=""1.0""?><One></One>")); 
     var obj2 = ser.Deserialize(new StringReader(@"<?xml version=""1.0""?><Two></Two>")); 
    } 
} 

Мне нужно десериализации XML (созданный не мной). Корневой тег может иметь разные имена, которые я должен сопоставлять с разными классами.

PS. Я знаю, что таких вопросов много. Я их изучил, но моя проблема все еще не решена.

ответ

1

Никакой шумихи вокруг моего вопроса. Сообщество может подумать, что это просто еще один глупый вопрос, заданный идиотом. Они могут быть правы. Я должен сам ответить, но будьте осторожны: ответ может быть и глупым.

Я закончил поиск корневого элемента XML, а затем сопоставил его с одним из известных типов и десериализовал с использованием этого типа. Как так:

public abstract class BaseClass{ } 

[XmlRoot("One")] 
public class ChildOne : BaseClass {} 

[XmlRoot("Two")] 
public class ChildTwo : BaseClass { } 

class Program 
{ 
    private static void Main(string[] args) 
    { 
     var known = new Type[] {typeof (ChildOne), typeof (ChildTwo)}; 
     var obj1 = Deserialize<BaseClass>(@"<?xml version=""1.0""?><One></One>", known); 
     var obj2 = Deserialize<BaseClass>(@"<?xml version=""1.0""?><Two></Two>", known); 
    } 

    private static T Deserialize<T>(string xml, Type[] knownTypes) 
    { 
     Type rootType = typeof (T); 

     if (knownTypes.Any()) 
     { 
      using (var reader = XmlReader.Create(new StringReader(xml))) 
      { 
       reader.MoveToContent(); 

       rootType = (from kt in knownTypes 
         let xmlRoot = kt.GetCustomAttributes<XmlRootAttribute>().FirstOrDefault() 
         where kt.Name == reader.Name || (xmlRoot != null && xmlRoot.ElementName == reader.Name) 
         select kt).FirstOrDefault() ?? typeof(T); 
      } 
     } 

     return (T) new XmlSerializer(rootType, knownTypes).Deserialize(new StringReader(xml)); 
    } 
} 
1

Чтобы расширить ваш ответ вы могли бы использовать немного LinqToXml для разбора XML, чтобы получить имя корня.

private T Deserialize<T>(string xml, Type[] knownTypes) 
{ 
    var rootType = knownTypes.FirstOrDefault(t => t.GetCustomAttributes<XmlRootAttribute>() 
                .Any(a => a.ElementName == XElement.Parse(xml).Name.LocalName)); 

    return (T)new XmlSerializer(rootType ?? typeof(T), knownTypes).Deserialize(new StringReader(xml)); 
} 
Смежные вопросы