2016-08-24 51 views
0

我有一個包含這樣解析XML具有正確的xsd:類型

<Value xsi:type="xsd:short">0</Value> 
<Value xsi:type="xsd:string">foo</Value> 
<Value xsi:type="xsd:boolean">false</Value> 
<!-- ... many other types --> 

元素如何可以自動解析/的方式,我得到Value元素在正確的.NET類型的內容反序列化這個XML that corresponds與xsd:type(例如System.Int16,System.StringSystem.Boolean)?

這是我嘗試過的,但它有點脆弱,所有這些.NET XML API都必須有內置的方式。

foreach (var value in XDocument.Load(new StreamReader(@"c:\bar.xml")).Descendants("Value")) 
{ 
    var actualValue = GetValue(value); 
} 

... 

// TODO: Get rid of this hand written method, .NET should do this for me 
private static object GetValue(XElement value) 
{ 
    XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance"; 
    var type = value.Attributes(ns + "type").Single().Value; 
    switch (type) 
    { 
     case "xsd:short": 
      return (short)value; 
     case "xsd:boolean": 
      return (bool)value; 
     case "xsd:string": 
      return (string)value;  
     ...     
    }   

    throw new UnknownTypeException(); 
} 

回答

0

假設你只能指望內建類型,你可以創建一個XML序列化反序列化值。幸運的是,您的屬性名稱與預期的名稱相匹配,因此您不需要執行任何轉換。

XNamespace xsd = "http://www.w3.org/2001/XMLSchema"; 
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance"; 
var doc = new XDocument(
    new XElement("root", 
     new XAttribute(XNamespace.Xmlns + "xsd", xsd), 
     new XAttribute(XNamespace.Xmlns + "xsi", xsi), 
     new XElement("Value", new XAttribute(xsi + "type", "xsd:short"), (short)0), 
     new XElement("Value", new XAttribute(xsi + "type", "xsd:string"), "foo"), 
     new XElement("Value", new XAttribute(xsi + "type", "xsd:boolean"), false) 
    ) 
); 

var serializer = new XmlSerializer(typeof(object), new XmlRootAttribute("Value")); 
var values = doc.Descendants("Value") 
    .Select(v => serializer.Deserialize(v.CreateReader())); 
-1

試試這個

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Linq; 

namespace ConsoleApplication11 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<object> values = new List<object>(); 
      string xml = 
       "<Root xmlns:xsi = \"abc\">" + 
        "<Value xsi:type=\"xsd:short\">0</Value>" + 
        "<Value xsi:type=\"xsd:string\">foo</Value>" + 
        "<Value xsi:type=\"xsd:boolean\">false</Value>" + 
       "</Root>"; 
      XElement root = XElement.Parse(xml); 
      XNamespace ns = root.GetDefaultNamespace(); 
      foreach(XElement value in root.Descendants("Value")) 
      { 
       string _type = (string)value.Attributes().Where(x => x.Name.LocalName == "type").FirstOrDefault(); 
       switch (_type) 
       { 
        case "xsd:short" : 
         values.Add((short)value); 
         break; 
        case "xsd:string": 
         values.Add((string)value); 
         break; 
        case "xsd:boolean": 
         values.Add((Boolean)value); 
         break; 
       } 

      } 

     } 
    } 
} 
+0

這與我的解決方案有什麼不同?我的解決方案已經可行由於switch語句,我想徹底擺脫'GetValue' *方法*。你只是插入了這個方法。 – bitbonk