[Resolved][3.0/LINQ] XML and LINQ, Node/Element list problem
Hi,
I have an XML file which populates an ASP.Net Treeview. It's basically built up like this:
Code:
<root>
<Category Name="Something">
<Item Someattribute="Something" />
<Item Someattribute="Something" />
</Category>
<Category Name="Something">
<Category Name="Something">
<Item Someattribute="Something" />
<Item Someattribute="Something" />
</Category>
<Item Someattribute="Something" />
<Item Someattribute="Something" />
</Category>
</root>
Now, this works perfectly, every subelement, get's added just like in the XML file. (Yes, I am confusing elements with nodes, or vice versa - if someone could give me a clear explanation on what the difference is, that'd be great :)).
What I now want to is load this XML file on my own, that I might create a fancy admin for the treeview. The idea I came up with was to create a recursive method that would call itself each time it hit a Category node(?). So, I made this:
Code:
private static void fillCategories(IEnumerable<XElement> list, List<XMLToolboxCategory> CatList)
{
var q = from x in list
select x;
foreach (var x in q)
{
var CatItems = new List<XMLToolboxItem>();
var Cat = new XMLToolboxCategory();
var qItems = from itm in x.Elements()
select itm;
foreach (var itm in qItems)
{
if (itm.Name == "Category")
{
Cat.CategoryList = new List<XMLToolboxCategory>();
fillCategories(itm.Descendants("Category"), Cat.CategoryList);
}
else
{
CatItems.Add(new XMLToolboxItem() { Filename = itm.Attribute("Filename").Value, Value = itm.Attribute("Value").Value, Type = itm.Name.ToString(), parent = itm.Parent });
}
}
CatList.Add(new XMLToolboxCategory() { Name = x.Attribute("Name").Value, ToolList = CatItems });
}
}
The two classes XMLToolboxItem and XMLToolboxCategory basically just hold some objects, it's rather straight forward. One important thing though, is that each XMLToolboxCategory can hold another Category and so forth, to implement the hierarchy from the XML into my objects.
I then call my method simply with:
Code:
Categories = new List<XMLToolboxCategory>();
var xtbox = XDocument.Load(filePath);
fillCategories(xtbox.Descendants("Category"), Categories);
The result is, that i load every element(?) just fine. However, my hierarchy isn't preserved - the method fillCategories() never calls itself.
So, I figure the problem lies in the list that XElement/XDocument.Descendants(XName) returns - it must return a complete list of all the elements(?) within all the Category nodes(?) instead of just the ones relative to it.
I hope I'm not sounding to cryptic on this one :) - as always, any help is appreciated.
Thanks in advance.
Re: [3.0/LINQ] XML and LINQ, Node/Element list problem
Anyone? I guess what I really want is some way of looping through each category node, and then recall the method whenever it hits a new nested category node.
Re: [3.0/LINQ] XML and LINQ, Node/Element list problem
Ok, looking through your code.
First, an element is a type of node. In your XML, anything can be considered a node, an attribute is an attribute node, the text is a text node, and so on.
Second, this isn't necessary:
Code:
var q = from x in list
select x;
list is already IEnumerable Xelement, so you're not really doing anything in that LINQ. Therefore this is not making any sense:
Code:
foreach (var x in q)
I'm guessing it never enters the loop? (Just a guess, you should step through your code)
Try that as a start...
Re: [3.0/LINQ] XML and LINQ, Node/Element list problem
Yea, that shouldn't be there, remnant of something else I tried. Yes I've tried setting up break points, and it does enter the loop, because XMLToolItems are added to the toolitem list - what seems to be the problem is that i basically just skips past every node with the name "Category" and just loops through everything else, not taking the hierarchy into consideration.
Re: [3.0/LINQ] XML and LINQ, Node/Element list problem
Paste your non-remnant code please.
Re: [3.0/LINQ] XML and LINQ, Node/Element list problem
Neo, would it be possible to upload a sample? I'm sure you're using XML more complex than that. I could try to run it on my machine and see what's happening. Therefore, it'd help to see what XMLToolboxCategory, etc., are and how they're defined.
From what I see right now, there's only one level of "Category" nodes, so I don't see it really entering the loop much.
Re: [3.0/LINQ] XML and LINQ, Node/Element list problem
It just occurred to me that .Descendants() will get you all the descendants of the node you asked for that match that XName. That means nested <categories> as well, in document order.
http://msdn2.microsoft.com/en-us/library/bb353813.aspx
That would explain why it doesn't go recursive. Try .Elements() instead.
Re: [3.0/LINQ] XML and LINQ, Node/Element list problem
Hi,
Yea, that's exactly the problem, I'm looking for a list that doesn't return all the nested categories. Gonna take a look at it later today and get back to you, if I can't get it to work, i'll upload the class w/ the .xml file.
Thanks a lot for your help so far!
1 Attachment(s)
Re: [3.0/LINQ] XML and LINQ, Node/Element list problem
Elements("Category") seems to be returning an empty list :/.
I've attached the classes used, together with the XML file if you wanna take a look at it.
Re: [Resolved][3.0/LINQ] XML and LINQ, Node/Element list problem
Okay, so basically, this just goes to show that I'm an idiot :).
After looking over the method again and again, I began to see stuff that didn't really add up, because I spent so much time moving diffrerent lines of code around to make it work.
I rewrote everything, this time using the list returned by "Elements()" - and now it works like a charm :). Thanks for wasting your time mendhak ;).
Just in case anyone might find it interesting, the final method is provided below:
Code:
private static void fillCategories(IEnumerable<XElement> list, List<XMLToolboxCategory> CatList)
{
foreach (var x in list)
{
var CatItems = new List<XMLToolboxItem>();
var Cat = new XMLToolboxCategory();
Cat.Name = x.Attribute("Name").Value;
foreach (var itm in x.Elements())
{
if (itm.Name == "Category")
{
if (Cat.CategoryList == null) { Cat.CategoryList = new List<XMLToolboxCategory>(); }
fillCategories(new List<XElement>() { itm }, Cat.CategoryList);
}
else
{
CatItems.Add(new XMLToolboxItem() { Filename = itm.Attribute("Filename").Value, Value = itm.Attribute("Value").Value, Type = itm.Name.ToString(), parent = itm.Parent });
}
}
Cat.ToolList = CatItems;
CatList.Add(Cat);
}
}
//Then I call it with:
fillCategories(SomeXDocument.Elements("root"), listToBePopulated);
Re: [Resolved][3.0/LINQ] XML and LINQ, Node/Element list problem
Glad to know... one of my first Linq answers ever!