2017-02-09 31 views
2

我有許多XML模式最有效的方法來確定如何使用類反序列化XML

例如

XML 1.0多xsd文件 - xml_1_0.xml

<?xml version="1.0" encoding="UTF-8"?> 
    <cars version="1.00"> 
     <car>Honda</car> 
     <car>Ferrari</car> 
    </cars> 

XML 2.0 - xml_2_0.xml

<?xml version="1.0" encoding="UTF-8"?> 
<cars version="2.00"> 
    <car> 
     <name>Honda</name> 
     <color>White</color> 
    </car> 

    <car> 
     <name>Honda</name> 
     <color>Red</color> 
    </car> 
</cars> 

我創建的.xsd我的課像這樣

xsd.exe cars_1_0.xsd /c 

xsd.exe cars_2_0.xsd /c 

和反序列化這樣的:

foreach(string file in files) { 
    XmlDocument doc = new XmlDocument(); 
    doc.Load(file);  
    string version = doc.SelectSingleNode("/Cars/@version").Value; 

    if(version == "1.00") 
    { 
     Stream reader = new FileStream(file, FileMode.Open); 
     XmlSerializer serializer = new XmlSerializer(typeof(v1.Cars)); 

     v1.Cars XML = new v1.Cars(); 
     XML = (v1.Cars)serializer.Deserialize(reader); 
    } 
    else if(version == "2.00") 
    { 
     Stream reader = new FileStream(file, FileMode.Open); 
     XmlSerializer serializer = new XmlSerializer(typeof(v2.Cars)); 

     v2.Cars XML = new v2.Cars(); 
     XML = (v2.Cars)serializer.Deserialize(reader); 
    } 
} 

有誰知道更好的方式來做到這一點,或有更好的表現?

+0

你能分享實際的XSD嗎?是修改XSD的一個選項?正在創建一個新的課程選項? –

+0

在我寫的例子中,xsd文件比較複雜,任何版本的xml都有很多其他的屬性 –

回答

1

你有幾個選擇,取決於你想採取多遠。一個非侵入性的選擇是不使用XmlDocument並避免不止一次加載流。例如,現有的代碼可以簡化/精簡到:

foreach (string file in files) 
{ 
    using (var stream = new FileStream(file, FileMode.Open)) 
    { 
     var settings = new XmlReaderSettings(); 
     settings.CloseInput = false; 
     string version = ""; 
     using (var xmlReader = XmlReader.Create(stream)) 
     { 
      if (xmlReader.ReadToFollowing("Cars")) 
      { 
       version = xmlReader.GetAttribute("version"); 
      } 
      else 
      { 
       throw new XmlException("Could not get 'version' attribute of 'Cars' root element!"); 
      }      
     } 
     stream.Position = 0; 
     if (version == "1.00") 
     { 
      XmlSerializer serializer = new XmlSerializer(typeof(v1.Cars)); 

      v1.Cars XML = new v1.Cars(); 
      XML = (v1.Cars)serializer.Deserialize(stream); 
     } 
     else if (version == "2.00") 
     { 
      XmlSerializer serializer = new XmlSerializer(typeof(v2.Cars)); 

      v2.Cars XML = new v2.Cars(); 
      XML = (v2.Cars)serializer.Deserialize(stream); 

     } 
    } 
} 

因爲你只是讀關閉根元素,你甚至可以從XmlReader與反序列化脫身,而不必重新設置在FileStream上的位置。

這避免了加載整個文件兩次(一次爲XmlDocument,然後再次爲XmlSerializer)的開銷 - 並且特別避免了爲每個文檔創建DOM的內存開銷。

更多的核選項將在一組定製類上實現IXmlSerializable,這將在ReadXml方法中具有定製邏輯來解析版本屬性並實例化正確的子類型。一個CarCollection類具有List<Car>屬性,其中Car是具有CarV1CarV2作爲後代的抽象類。這可以達到您可以獲得的效率(並且對您的類層次結構設計提供非常細緻的控制),但是會消除使用xsd.exe生成類的可能性。