[SOLVED] Looping through items and read desired elements

Issue

I have something like this:

<ITEMS ASOF_DATE="6/2/2022" RECORDS="1" CREATE_DATE="6/3/2022" >
    <ITEM>
        <port_name>95512M</port_name>
        <bench_name>LEHSECUR</bench_name>
        <SomeValue>-808</SomeValue>
    </ITEM>
    <ITEM>
        <port_name>95512M</port_name>
        <bench_name>LEHSECUR</bench_name>
        <SomeValue>-808</SomeValue>
        <SomeOtherValue>-808</SomeOtherValue>
    </ITEM> 
    <ITEM>
        <port_name>95512M</port_name>
        <bench_name>LEHSECUR</bench_name>
        <SomethingElse>234</SomethingElse>
    </ITEM> 
</ITEMS>

It can have multiple <ITEM> items and those can have multiple elements under it for example first item has three elements, second one has four , third one has three in this example.
I want to loop through all of these <ITEM> items and read some specific elements that I am interested in. For example <port_name> and <bench_name>

But I can’t figure out how to do the loop. For example root.SelectNodes("ITEMS") in my code below isn’t what I am hoping to be able to loop through its items.

 XmlDocument doc = new XmlDocument();
        doc.Load(myFilePath.ToString());
        XmlElement root = doc.DocumentElement;
        var lineItems = root.InnerXml;

        XmlNodeList nodes = root.SelectNodes("ITEMS");
        foreach (XmlNode node in nodes)
        {
            var somethingElse = node.SelectNodes("ITEM");
        }

Solution

Try using the Elements() or Descendants() methods to iterate your root element.

Edited in response to comment:

If you’re looking for something specific, I have found that one of the easiest ways to do this is to write an Extension Method for XElement that suites your requirements. Here is an example.

static class Extensions
{
    public static bool IsPortNameMatch(this XElement xElement, string name)
    {
        if (!string.Equals(xElement.Name.LocalName, "ITEM")) return false;
        var portName = xElement.Element("port_name");
        if (portName == null) return false;
        return string.Equals((string)portName, name);
    }
}

To test the extension, I have added a fourth ITEM to the source with a port_name of "UniquePortName". The new console output now reports this as "Found".

static void Main(string[] args)
{
    var root = XElement.Parse(source);
    foreach (var item in root.Elements("ITEM"))
    {
        foreach (var entry in item.Elements())
        {
            Console.WriteLine($"{entry.Name.LocalName} = {(string)entry}");
        }
    }
    // Find something specific
    var matchItem =
        root.Descendants("ITEM")
        .First(match => match.IsPortNameMatch("UniquePortName"));
    Console.WriteLine($"FOUND:{Environment.NewLine}{matchItem.ToString()}");

}
const string source =
@"<ITEMS ASOF_DATE=""6/2/2022"" RECORDS=""1"" CREATE_DATE=""6/3/2022"" >
    <ITEM>
        <port_name>95512M</port_name>
        <bench_name>LEHSECUR</bench_name>
        <SomeValue>-808</SomeValue>
    </ITEM>
    <ITEM>
        <port_name>95512M</port_name>
        <bench_name>LEHSECUR</bench_name>
        <SomeValue>-808</SomeValue>
        <SomeOtherValue>-808</SomeOtherValue>
    </ITEM> 
    <ITEM>
        <port_name>95512M</port_name>
        <bench_name>LEHSECUR</bench_name>
        <SomethingElse>234</SomethingElse>
    </ITEM>  
    <ITEM>
        <port_name>UniquePortName</port_name>
        <bench_name>LEHSECUR</bench_name>
        <SomethingElse>234</SomethingElse>
    </ITEM> 
</ITEMS>";
}

console output

Answered By – IVSoftware

Answer Checked By – Willingham (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.