I have
<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>
and the class
public class ChemieComponent
{
public string Name { get; set; }
public string Id { get; set; }
public double MolarMass { get; set; }
}
Can I with the LINQ query parse this components to objects? How? I the end should I have a IEnumerable, right?
EDIT
<Points>
<Point name="P1" pressure="1">
<Fractions>
<Fraction id="aaa" value="0.15272159"/>
<Fraction id="bbb" value="0.15272159"/>
</Fractions>
more points...
</Points>
You can use the following:
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
Accessing nested elements with Linq to Xml is also possible:
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"),
}
};
}
I realise this is an old post, but I've been doing some reading of XML into objects recently. I wasn't keen on Linq to XML - it's not very readable, relies on "magic strings", and requires code changes if the XML schema changes.
For anyone interested, I use the XmlSerializer
class to deserialize the XML into objects. Put the deserialization code into a generic helper method, and voila - one-line of code to deserialize an XML file into an object graph:-
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; }
}
A couple of caveats:-
This solution obviously relies on decorating the domain models with XML attributes, which may or may not be acceptable to you. The solution also relies on an outer element being present in the XML, and won't work if the root element is an array (<Points>
in this example).
It's not possible to specify IEnumerable<>
(which the OP mentioned); you can use arrays or List<>
.