2011-12-07 1 views
8

hoParse XML utilizzando LINQ to XML per classe di oggetti

<Model> 
    <Components> 
     <Component name="a" id="aaa" molarmass="60.05"/> 
     <Component name="b" id="bbb" molarmass="18.02"/> 
     <Component name="c" id="ccc" molarmass="32.04"/> 
     <Component name="d" id="ddd" molarmass="46.03"/> 
    </Components> 
    ... 
</Model> 

e la classe

public class ChemieComponent 
{ 
    public string Name { get; set; } 
    public string Id { get; set; } 
    public double MolarMass { get; set; } 
} 

Posso con la query LINQ analizzare questo componenti agli oggetti? Come? Io alla fine dovrei avere un IEnumerable, giusto?

EDIT

<Points> 
    <Point name="P1" pressure="1"> 
    <Fractions> 
     <Fraction id="aaa" value="0.15272159"/> 
     <Fraction id="bbb" value="0.15272159"/> 
    </Fractions> 
    more points... 
</Points> 

risposta

19

È possibile utilizzare il seguente:

XDocument doc = XDocument.Parse(xml); 
IEnumerable<ChemieComponent> result = from c in doc.Descendants("Component") 
             select new ChemieComponent() 
             { 
              Name = (string)c.Attribute("name"), 
              Id = (string)c.Attribute("id"), 
              MolarMass = (double)c.Attribute("molarmass") 
             }; 

EDIT

Accesso agli elementi annidati con LINQ to XML è anche possibile:

public class Point 
{ 
    public string Name { get; set; } 
    public int Pressure { get; set; } 

    public IEnumerable<Fraction> Fractions { get; set; } 
} 

public class Fraction 
{ 
    public string Id { get; set; } 
    public double Value { get; set; } 
} 

static void Main() 
{ 
    string xml = @"<Points> 
     <Point name='P1' pressure='1'> 
      <Fractions> 
       <Fraction id='aaa' value='0.15272159'/> 
       <Fraction id='bbb' value='0.15272159'/> 
      </Fractions> 
     </Point> 
     </Points>"; 

    XDocument doc = XDocument.Parse(xml); 
    IEnumerable<Point> result = from c in doc.Descendants("Point") 
           select new Point() 
           { 
            Name = (string)c.Attribute("name"), 
            Pressure = (int)c.Attribute("pressure"), 
            Fractions = from f in c.Descendants("Fraction") 
               select new Fraction() 
               { 
                Id = (string)f.Attribute("id"), 
                Value = (double)f.Attribute("value"), 
               } 
           }; 
} 
+0

Potrebbe voler verificare null o la vostra applicazione esploderà. –

+0

@Wouter: grazie! Funziona molto bene. Posso creare subquery? O dovresti fare due domande? Vedi la mia modifica per favore –

+0

@PedroDusso Ho aggiunto del codice per la selezione nidificata –

4

Mi rendo conto che questo è un vecchio post, ma di recente ho letto alcuni XML in oggetti. Non ero entusiasta di Linq per XML - non è molto leggibile, si basa su "stringhe magiche" e richiede modifiche al codice se lo schema XML cambia.

Per chiunque sia interessato, utilizzo la classe XmlSerializer per deserializzare l'XML in oggetti. Inserire il codice di deserializzazione in un metodo di supporto generici, e voilà - una riga di codice per deserializzare un file XML in un oggetto grafico: -

using System.IO; 
using System.Xml.Serialization; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var xml = @"<?xml version='1.0' encoding='utf-8' ?> 
      <Model> 
       <Points> 
        <Point name='P1' pressure='1'> 
         <Fractions> 
          <Fraction id='aaa' value='0.15272159'/> 
          <Fraction id='bbb' value='0.15272159'/> 
         </Fractions> 
        </Point> 
       </Points> 
      </Model>"; 

     var model = DeserializeObject<Model>(xml); 
    } 

    private static T DeserializeObject<T>(string xml) 
    { 
     var serializer = new XmlSerializer(typeof(T)); 
     using (var tr = new StringReader(xml)) 
     { 
      return (T)serializer.Deserialize(tr); 
     } 
    } 
} 

public class Model 
{ 
    [XmlArrayItem("Point")] 
    public Point[] Points { get; set; } 
} 

public class Point 
{ 
    [XmlAttribute(AttributeName = "name")] 
    public string Name { get; set; } 

    [XmlAttribute(AttributeName = "pressure")] 
    public int Pressure { get; set; } 

    [XmlArrayItem("Fraction")] 
    public Fraction[] Fractions { get; set; } 
} 

public class Fraction 
{ 
    [XmlAttribute(AttributeName = "id")] 
    public string Id { get; set; } 

    [XmlAttribute(AttributeName = "value")] 
    public double Value { get; set; } 
} 

Un paio di avvertenze: -

Questa soluzione si basa, ovviamente, sulla decorazione dei modelli di dominio con attributi XML, che possono o non possono essere accettabili per te. La soluzione si basa anche su un elemento esterno presente nell'XML e non funzionerà se l'elemento radice è un array (<Points> in questo esempio).

Non è possibile specificare IEnumerable<> (menzionato dall'OP); puoi utilizzare gli array o List<>.