Reputation: 553
I have the following xml structure
<userlist>
<user Name="something">
<function name="funcname">
<picture name="pictname">
<curve name="curvename">
<name>NAME</name>
...
</curve>
</picture>
</function>
<function name="function2">
...
</function>
</user>
It goes on a bit more. I have written a function to extract of the "function" tags and place them in objects using code that simplifies to this:
from function in xmlDoc.Descendants("function")
select new FUNCTIONOBJECT {
do all the rest...
}.toList<FUNCTIONOBJECT>();
I am now trying to make it so that I only filter the functions for a given user. so the name attribute of the user is given. Can anyone tell me how I can make this work with LINQ? My attempt was:
from user in xmlDoc.Descendants("user")
where user.Attribute("Name").Value == givenusername
select {
var functions =
from function in user.Descendants("function")
select new FUNCTIONOBJECT {
... more stuff
}.toList<FUNCTIONOBJECT>();
But this is wrong and doesnt work. All help is good. I am pretty new to c# and still trying to wrap my head around xml parsing with LINQ.
EDIT: updated version of what I have and still doesnt work:
XDocument xmlDoc = XDocument.Load(path);
var functionlist =
(from user in xmlDoc.Descendants("user")
where user.Attribute("Name").Value == username
select(
(from function in user.Descendants("function")
select new Function
{
name = function.Attribute("name").Value,
pictures =
(from picture in function.Descendants("picture")
select new Picture
{
name = picture.Attribute("name").Value,
layout = picture.Element("layout").Value,
curves =
(from curve in picture.Descendants("curve")
select new Curve
{
name = curve.Attribute("name").Value,
section = curve.Element("section").Value,
run = curve.Element("run").Value,
folder = curve.Element("folder").Value,
drivingpoint = curve.Element("drivingpoint").Value,
display = int.Parse(curve.Element("display").Value),
points =
(from point in curve.Descendants("point")
select new Point
{
id = point.Element("id").Value != null ? point.Element("id").Value : string.Empty,
direction = point.Element("direction").Value != null ? point.Element("direction").Value : string.Empty,
}).ToList<Point>(),
}).ToList<Curve>(),
}).ToList<Picture>(),
}).ToList<Function>(),
).toList();
}
Upvotes: 1
Views: 1349
Reputation: 13022
Just few syntax mistakes. Otherwise, the content was correct. Its a bit tricky to learn C# and LINQ syntax at the same time (a language in a language). Here is the corrected code:
from user in xmlDoc.Descendants("user")
where user.Attribute("Name").Value == givenusername
select ((from function in user.Descendants("function") // When you do a "select something" "something" must have a value, so you can't begin with "{ var functions = ..."
select new FUNCTIONOBJECT
{
// more stuff
}).ToList(); // You don't have to specify <FUNCTIONOBJECT> because the compiler deduce it from the context (here there a new FUNCTIONOBJECT
But here, you will have a List<List<FUNCTIONOBJECT>>
. Why? Because there is no information in the code that specify that only 1 user has the givenusername
.
If it is the case, just split the code:
// Gets the user
var user = (from user in xmlDoc.Descendants("user")
where user.Attribute("Name").Value == givenusername
select user).Single(); // Get the only user that satisfy the condition (Throw an exception if no user has the given name or if multiple users have the given name)
// Gets its functions
List<FUNCTIONOBJECT> functions = (from function in user.Descendants("function")
select new FUNCTIONOBJECT
{
// more stuff
}).ToList();
Upvotes: 4