2014-02-28 101 views
3

所以,如果我有3個不同的文件,其中包含非常長和複雜的xml(我在這裏縮寫),但只是根元素名稱是不同的(不是真的隨機,但我寧願不重複類同一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:

<車>是沒有預料到。

這似乎很不好意思;重命名根元素,然後反序列化取元素並以<?xml>爲標籤前綴。還有其他建議嗎?

回答

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

由於缺乏關於XML名稱空間的知識,我發現這是名稱空間也導致了一個額外的錯誤與相同的描述:(。 –

1

我沒有想出這只是調整了它的一些,原來是:Deserialize XML To Object using Dynamic

不知道這是否是你所需要的東西,但它可以讓你搶從XML的價值和把它們放進你的班級。如果在一個xml文檔中有多個汽車,它也可以針對數組或集合進行調整。

您需要添加:

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; 
    } 
} 
+0

因爲XML具有數百個節點,它會更容易做到這一點與Linq2Xml然後更新ParseXml方法(這對我來說似乎更令人費解)。 –

+0

@ErikPhilips這是有道理的,如果你正在處理與許多不同的節點名稱的巨大的XML消息。我解析了很多xml,但是已經從xsds構建了類,所以xml可以很好地反序列化到我的對象中。如果我在我的xml中獲得額外的元素,他們會在deserilization期間被忽略。無論如何,就像我說的,我不確定它是否適合你。 – Popo