Search code examples
c#xmllinq-to-xml

Select multiple elements with Linq to XML


I have a C# application and need to extract multiple elements from a Linq to XML collection.

I have the following extract from an XML file

    <SNS>
    <uniqueSystem><system>49</system><label>Engines</label>
        <uniqueSubsystem><subsystem>30</subsystem><label>APU</label>
            <uniqueUnit><unit>00</unit><label>Starter</label>
    </uniqueUnit>
    </uniqueSubsystem>
    </uniqueSystem>
    <uniqueSystem><system>50</system><label>Hydraulics</label>
        <uniqueSubsystem><subsystem>30</subsystem><label>Reservoir</label>
            <uniqueUnit><unit>00</unit><label>Pump</label>
    </uniqueUnit>
    </uniqueSubsystem>
</uniqueSystem></SNS>

I need to extract the values from within each 'uniqueSystem' element. So in the example above, under the 'SNS' element there are 2 'uniqueSystem' elements, and within each of these there are 'uniqueSubsystem' elements and 'uniqueUnit' elements each with 'label' elements. I need to extract this data to build a TreeView.

My problem is extracting multiple elements using Linq. How do i do this?

At the moment i have

var item = from items in doc.Descendants("SNS").Descendants("uniqueSystem").Descendants("system")
                          orderby items.Value
                          select items.Descendants("uniqueSystem");

I think this will give me a collection of the 'uniqueSystem' elements, from which i now need to extract the values of the multiple elements within. Can anybody please help?

My next attmpt is as follows, but this is giving me a null reference exception:

var item = from items in doc.Descendants("SNS").Descendants("uniqueSystem").Descendants("system")
                          orderby items.Value
                          select items.Descendants("uniqueSystem");

                foreach (var e in item)
                {
                    string sys = e.Descendants("system").FirstOrDefault().Value;
                    string sysLabel = e.Descendants("system").Descendants("label").FirstOrDefault().Value;

                    string subsys = e.Descendants("subsystem").FirstOrDefault().Value;
                    string subsysLabel = e.Descendants("subsystem").Descendants("label").FirstOrDefault().Value;

                    string unit = e.Descendants("unit").FirstOrDefault().Value;
                    string unitLabel = e.Descendants("unit").Descendants("label").FirstOrDefault().Value;

                    buildSystemNodes(sys, sysLabel);
                    //getSubSystems(myitem);
                }

Solution

  • So the code I have written below will generate the tree view. The treeview class that I am using is in the namespace System.Web.UI.WebControls. The function is however O(n^3).

        public void ProcessXml(string document)
        {
            var doc = XDocument.Parse(document, LoadOptions.None);
            var uniqueSystemList = doc.Element("SNS").Elements();
    
            var treeView = new TreeView();
            string value = string.Empty;
            string text = string.Empty;
            foreach (var uniqueSystem in uniqueSystemList)
            {
                value = uniqueSystem.Element("label").Value.ToString();
                text = uniqueSystem.Element("system").Value.ToString();
                var uniqueSystemNode = new TreeNode(text, value);
                var uniqueSubsystemList = uniqueSystem.Elements("uniqueSubsystem");
                foreach (var uniqueSubSystem in uniqueSubsystemList)
                {
                    value = uniqueSubSystem.Element("label").Value.ToString();
                    text = uniqueSubSystem.Element("subsystem").Value.ToString();
                    var uniqueSubSystemNode = new TreeNode(text, value);
                    var uniqueUnitList = uniqueSubSystem.Elements("uniqueUnit");
                    foreach (var uniqueUnit in uniqueUnitList)
                    {
                        value = uniqueUnit.Element("label").Value.ToString();
                        text = uniqueUnit.Element("unit").Value.ToString();
                        var uniqueUnitNode = new TreeNode(text, value);
                        uniqueSubSystemNode.ChildNodes.Add(uniqueUnitNode);
                    }
                    uniqueSystemNode.ChildNodes.Add(uniqueSubSystemNode);
                }
                treeView.Nodes.Add(uniqueSystemNode);
            }
        }