1

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();
    }

1 Answer 1

4

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();  
Sign up to request clarification or add additional context in comments.

1 Comment

have updated my version but it still doesnt work. Could you check my edit to the original post to see what I am doing wrong.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.