使用不同的根元素名称反序列化

5
以下示例引发了“[One xmlns=''] was not expected.”异常。
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。我知道有很多类似的问题。我已经研究过它们,但我的问题仍未解决。

2个回答

3

请不要对我的问题进行夸大宣传。社区可能认为这只是一个白痴问的又一个愚蠢的问题。他们可能是对的。我必须自己回答,但请注意:答案也可能很愚蠢。

最终,我探测了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));
    }
}

我正在寻找的东西! - LeffBA

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));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接