将xml的一部分反序列化为类

时间:2014-02-28 00:10:44

标签: c# xmlserializer xml-deserialization

因此,如果我有3个不同的文件,其中包含非常长且复杂的xml(我在这里已经缩写),但只是根元素名称不同(不是非常随机但我不想为同一个xml重复类) :

档案1

<?xml version="1.0"?>
<somerootname1>
  <car>
    <make>honda</make>
    <model>civic</model>
  </car>
</somerootname1>

文件2

<?xml version="1.0"?>
<somerootname2>
  <car>
    <make>honda</make>
    <model>civic</model>
  </car>
</somerootname2>

档案3

<?xml version="1.0"?>
<somerootname3>
  <car>
    <make>honda</make>
    <model>civic</model>
  </car>
</somerootname3>

因为XmlRootAttributeAllowMultiple=false我无法创建一个类来表示以前的xml。

  

复制'XmlRootAttribute'属性

[XmlRoot(ElementName="somerootname1")]
[XmlRoot(ElementName="somerootname2")]
public class Root
{
  public Automobile Car { get; set; }

}

public class Automobile 
{
  public string Make { get; set; }
  public string Model { get; set; }
}

我以为我可能会偷偷摸摸地抓住我需要的元素并将其反序列化:

var xDoc = XDocument.Parse("myfile.xml");

var xCar = xDoc.Root.Descendants()
  .FirstOrDefault(d => d.Name.LocalName.Equals("car"))

var serializer = new XmlSerializer(typeof(Automobile))
using (var reader = xml.CreateReader())
{
  result = (Automobile)serializer.Deserialize(reader);
}

然而,这会产生InvalidOperationException

  

XML文档(0,0)中存在错误。

使用InnerException:

  

&LT;汽车&GT;没想到。

这两者似乎都很狡猾;重命名根元素,然后反序列化 OR 获取元素并为<?xml>标记添加前缀。还有其他建议吗?

2 个答案:

答案 0 :(得分:1)

我没有提出这个,但只是调整了一下,原文来自:Deserialize XML To Object using Dynamic

不确定它是否正是您所需要的,但它允许您从xml中获取值并将它们放入您的类中。如果一个xml doc中有多个汽车,它也可以针对数组或集合进行调整。

您需要添加:

using System.Dynamic;
using System.Xml.Linq;


    protected Car ParseXml(Car NewCar) {          
        string xml = "<?xml version=\"1.0\"?><somerootname1>  <car>    <make>honda</make>    <model>civic</model>  </car></somerootname1>";            
        dynamic car = DynamicXml.Parse(xml);            
        NewCar.Make = car.car.make;
        NewCar.Model = car.car.model;
        return NewCar;
    }

[Serializable]
public partial class Car
{
    public Car() { }

    public string Make { get; set; }

    public string Model { get; set; }
}


public class DynamicXml : DynamicObject
{
    XElement _root;
    private DynamicXml(XElement root)
    {
        _root = root;
    }

    public static DynamicXml Parse(string xmlString)
    {
        return new DynamicXml(XDocument.Parse(xmlString).Root);
    }

    public static DynamicXml Load(string filename)
    {
        return new DynamicXml(XDocument.Load(filename).Root);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = null;

        var att = _root.Attribute(binder.Name);
        if (att != null)
        {
            result = att.Value;
            return true;
        }

        var nodes = _root.Elements(binder.Name);
        if (nodes.Count() > 1)
        {
            result = nodes.Select(n => new DynamicXml(n)).ToList();
            return true;
        }

        var node = _root.Element(binder.Name);
        if (node != null)
        {
            if (node.HasElements)
            {
                result = new DynamicXml(node);
            }
            else
            {
                result = node.Value;
            }
            return true;
        }

        return true;
    }
}

答案 1 :(得分:1)

您已经提取了<car>节点,但您仍在从文档的根节点反序列化。这就是为什么异常表明它期待<car>节点。以下适用于我:

[XmlRoot("car")]
public class Automobile
{
    [XmlElement("make")]
    public string Make { get; set; }
    [XmlElement("model")]
    public string Model { get; set; }
}

<car>反序列化:

var xCar = xDoc.Root.Descendants()
    .FirstOrDefault(d => d.Name.LocalName.Equals("car"));

var serializer = new XmlSerializer(typeof(Automobile));
using (var reader = xCar.CreateReader())
{
    var result = (Automobile)serializer.Deserialize(reader);
    Console.WriteLine(result.Make);
    Console.WriteLine(result.Model);
}