views:

40

answers:

2

We've got a Class called Group, it contains a collection of questions and it also contains collection of groups (i.e. we have a potential nesting of groups).

Expressed in XML this might look something like this:

<group id="Group1">
  <questions>
      <question id="questions11"/>
  </questions>
  <groups>
    <group id="group12">
      <questions>
          <question id="question121"/>
      </questions>
      <groups>
        <group id ="group121">
          <questions>
             <question id="question1211"/>
          </questions>
        </group>
        <group id ="group122">
          <questions>
            <question id="question1221"/>
          </questions>
        </group>        
      </groups>
    </group>
    <group id="group13">
      <questions>
          <question id="question131"/>
      </questions>
    </group>
  </groups>
</group>

I've actually simplified the structure, for brevity I've omitted bunch of properties in each group that I'll want to include in the projection.

What I want to do is shape a new type that includes the hierachical structure here and some of the properties but excludes some others and the questions.

I'm utterly stuck on hwo to do this in linq. I had a look at SelectMany but that wasn't what I wanted.

TIA

A: 

You will need to make a recursive function that turns a <group> element into a Group instance and calls itself for the child <group> elements.

SLaks
Yeah, just to clarify for anybody else the xml was just to illustrate the data structure. I'm actually querying over objects with contained collections. I figured I'd need some kind of function to be called recursively, but being kinda new to Linq I just wasn't sure of the syntax to use for the query.
A: 

Well... I'm not sure what objects you would be working with, but if it was coming from xml, you might try something similar to this:

    public class Group
    {
        public string Id { get; set; }
        IEnumerable<Question> Questions { get; set; }
        IEnumerable<Group> Groups { get; set; }

        public static IEnumerable<Group> Extract(XElement groupElement)
        {
            var groups = new List<Group>();
            var group = new Group{ Id = groupElement.Attribute("id").Value};
            groups.Add(group);

            // Extract questions.
            var questionsSubRoot = groupElement.Element("questions");
            if (questionsSubRoot != null)
                group.Questions = Question.Extract(questionsSubRoot);

            // Extract subgroups.
            var groupsElement = groupElement.Element("groups");
            if (groupsElement != null)
                group.Groups = groupsElement.Elements("group").SelectMany(elem => Group.Extract(elem));

            return groups;
        }
    }

and for your Questions class...

    public class Question
    {
        public string Id { get; set; }

        public static IEnumerable<Question> Extract(XElement questionsElement)
        {
            return questionsElement.Elements().Select(elem => new Question { Id = elem.Attribute("id").Value });
        }
    }

You would call it like...

var xDoc = XDocument.Parse(xml);
var groups = Group.Extract(xDoc.Element("group"));
Software.Developer
Ooops...sorry forgot to mark an answer on this question. I was kind of asking the wrong question really. Thanks for taking the time to reply though and it's a nice answer. Just not the question I asked (which wasn't a great one in the first place <ahem>