【问题标题】:deserialize with different root element names使用不同的根元素名称反序列化
【发布时间】:2013-08-08 00:34:00
【问题描述】:

以下示例给出了“[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(不是我生成的)。根标签可能有不同的名称,我必须映射到不同的类。

附言。我知道周围有很多这样的问题。我研究过它们,但我的问题仍然没有解决。

【问题讨论】:

    标签: c# xml xml-serialization xmlserializer


    【解决方案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));
        }
    }
    

    【讨论】:

    • 我在找什么!
    【解决方案2】:

    要扩展您的答案,您可以使用一点 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));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 2012-04-14
      • 1970-01-01
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      相关资源
      最近更新 更多