繁体   English   中英

在C#中将嵌套的XML元素反序列化为类

[英]Deserialize nested XML element into class in C#

我有以下XML结构(为简洁而编辑),我无法控制。

<GetVehicles>
    <ApplicationArea>
        <Sender>
            <Blah></Blah>
        </Sender>
    </ApplicationArea>
    <DataArea>
        <Error>
            <Blah></Blah>
        </Error>
        <Vehicles>
            <Vehicle>
                <Colour>Blue</Colour>
                <NumOfDoors>3</NumOfDoors>
                <BodyStyle>Hatchback</BodyStyle>
            <Vehicle>
        </Vehicles>
    </DataArea>
</GetVehicles>

我有以下课程:

[XmlRoot("GetVehicles"), XmlType("Vehicle")]
public class Vehicle
{
    public string Colour { get; set; }
    public string NumOfDoors { get; set; }
    public string BodyStyle { get; set; }
}

我希望能够将XML反序列化为此Vehicle类的单个实例。 99%的情况下,XML应该只返回一个'Vehicle'元素。 如果它在'Vehicles'元素中包含多个'Vehicle'元素,我还没有处理它。

不幸的是,XML数据当前没有映射到我的类属性; 在调用我的Deserialize方法时,它们被留空了。

为了完整性,这是我的Deserialize方法:

private static T Deserialize<T>(string data) where T : class, new()
{
    if (string.IsNullOrEmpty(data))
        return null;

    var ser = new XmlSerializer(typeof(T));

    using (var sr = new StringReader(data))
    {
        return (T)ser.Deserialize(sr);
    }
}

我不关心其他更多的父元素,如'ApplicationArea','Error'等。我只对提取'Vehicle'元素中的数据感兴趣。 如何让它只从XML反序列化这些数据?

以伊利亚的答案为基础:

这可以略微优化,因为已经有一个加载的节点:没有必要将xml传递给字符串(使用vehicle.ToString() ),只是为了使序列化程序必须重新解析它(使用StringReader )。

相反,我们可以使用XNode.CreateReader直接创建一个阅读器:

private static T Deserialize<T>(XNode data) where T : class, new()
{
    if (data == null)
        return null;

    var ser = new XmlSerializer(typeof(T));
    return (T)ser.Deserialize(data.CreateReader());
}

或者,如果数据是XmlNode ,请使用XmlNodeReader

private static T Deserialize<T>(XmlNode data) where T : class, new()
{
    if (data == null)
        return null;

    var ser = new XmlSerializer(typeof(T));
    using (var xmlNodeReader = new XmlNodeReader(data))
    {
        return (T)ser.Deserialize(xmlNodeReader);
    }
}

然后我们可以使用:

var vehicle = XDocument.Parse(xml)
                       .Descendants("Vehicle")
                       .First();

Vehicle v = Deserialize<Vehicle>(vehicle);

我不了解您问题的完整背景,因此此解决方案可能不适合您的域。 但一种解决方案是将您的模型定义为:

[XmlRoot("Vehicle")] //<-- optional
public class Vehicle
{
    public string Colour { get; set; }
    public string NumOfDoors { get; set; }
    public string BodyStyle { get; set; }
}

并使用LINQ to XML将特定节点传递给Deserialize方法:

var vehicle = XDocument.Parse(xml)
                       .Descendants("Vehicle")
                       .First();

Vehicle v = Deserialize<Vehicle>(vehicle.ToString());


//display contents of v 
Console.WriteLine(v.BodyStyle);   //prints Hatchback
Console.WriteLine(v.Colour);      //prints Blue
Console.WriteLine(v.NumOfDoors);  //prints 3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM