An XML needs to be parsed – I was told the other day. My first questions from experience, how big the XML is going to be? Do we know the schema? The answer : It’s never going to be bigger than few lines, as we use it to store our application’s menu – which may or may not have child(ren). And yes we know the XML schema. Enough said. Now I needed just one more ingredient, a sample XML. I was not thinking to have an extra schema class, the schema was unlikely to change as we controlled it ( if not, I would definitely have re-thought the approach depending on the answers to my questions above )
It looked something like below :
<?xml version='1.0' encoding='utf-8' ?> <Menu> <Group> <Item Label='Menu1' Href='/Menu1/Dashboard'> <Group> <Item Label='Menu 1 Screen1' Href='/Menu1/Screen1' /> </Group> </Item> <Item Label='Menu2' Href='/Menu2'> <Group> <Item Label='Menu 2 Screen 1' Href='/Menu2/Screen1' /> <Item Label='Menu 2 Screen 2' Href='/Menu2/Screen2' /> </Group> </Item> <Item Label='Menu3' Href='/Menu3'> <Group> <Item Label='Service 1' Href='http://service1.asmx'/> <Item Label='Menu 3 Screen 1' Href='/Menu3/Screen1' /> <Item Label='Menu 3 Screen 2' Href='/Menu3/Screen2' /> </Group> </Item> <Item Label='Menu 3 w/o child' Href='/Menu3' /> </Group> </Menu>
Alright, for my first prototype I need a list of menu labels and their corresponding child(ren). I know I can use LINQ to XML and blend it with some XPath query for quick and easy solution, I know the XML is pretty small, so I do not have to worry about a fast, read-only cache for XML document processing by using XSLT by using the XPathNavigator interface. I just needed something short and sweet. So I know that the parent elements could be accessed using /Menu/Group/Item. And then I would iterate through each, and within each such node, /Group/Item would give me the child(ren) elements, if any. Simple plan of attack.
Next thing, I fire up my LINQ-pad and start writing the code and ended up with following ( I have replaced the LINQ-pad’s Dump() with Console.WriteLine() if you still have not fallen for LINQ-pad or have been living in a cave and wondering what it is )
// using System; // using System.Collections.Generic; // using System.Linq; // using System.Xml.Linq; // using System.Xml.XPath; XDocument xDocument = XDocument.Parse(xml); string[] childLabelAttributeValues = null; IEnumerable<XElement> childElements = null; XAttribute labelAttribute = null; var rootElements = xDocument.XPathSelectElements("./Menu/Group/Item"); foreach (var rootElement in rootElements) { childElements = rootElement.XPathSelectElements("./Group/Item"); labelAttribute = rootElement.Attributes("Label").FirstOrDefault(); if (labelAttribute != null) { Console.WriteLine(labelAttribute.Value); } // drill for any child element if (childElements != null && childElements.Count() > 0) { //Console.WriteLine(string.Format("\tHas {0} child(ren)", childElements.Count())); childLabelAttributeValues = childElements.Select(e => e.Attributes("Label").FirstOrDefault().Value).ToArray<string>(); Console.WriteLine("\t" + string.Join(", ", childLabelAttributeValues)); } }
Just a quick post. So I kept it simple. In reality this code should somehow spit out some data-structure (if using any 3rd party controls) or if I was to use this XML directly in the front end w/o much complexity, I would not even bother writing the code above in C# since you could also do XPath in JavaScript !
Either way, C# or JavaScript but one thing I would definitely make sure to have is a recursive check for children ( keep drilling )