Eternal Learner
Eternal Learner

Reputation: 121

Read All Sibling Node Elements

I have a situation where I have an xml file that looks like this:

<initialize>
 <boxes>
  <box>
     <compliment>RayTest1</compliment>
     <description>RayTest1</description>
     <boxtype>RayTest</boxtype>
     <il>1.00</il>
     <ib>1.00</ib>
     <ih>1.00</ih>
     <ol>1.00</ol>
     <ob>1.00</ob>
     <oh>1.00</oh>
     <bw>1.00</bw>
     <bgw>1.00</bgw>
     <boxstrength>1</boxstrength>
  </box>
  <box>
     <compliment>RayTest2</compliment>
     <description>RayTest2</description>
     <boxtype>RayTest</boxtype>
     <il>99.99</il>
     <ib>99.99</ib>
     <ih>99.99</ih>
     <ol>99.99</ol>
     <ob>99.99</ob>
     <oh>99.99</oh>
     <bw>99.99</bw>
     <bgw>99.99</bgw>
     <boxstrength>99</boxstrength>
  </box>
 </boxes>
</initialize>

What I need to accomplish in C# is this:

A user is going to upload an xml file to my page.

I need to parse through each box of the xml file, assign the values to an object, and then add that object to a list for display in an ASP.NET MVC App.

I've attempted to do this in the following way:

                try
                {
                    List<BoxViewModel> boxesList = new List<BoxViewModel>();
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(fileFromPage.FileName);

                    XmlNodeList boxNodeList = xmlDoc.SelectSingleNode("//initialize/boxes").ChildNodes;

                    foreach (XmlNode boxNode in boxNodeList)
                    {
                        XmlNode currentBoxNode = boxNode;
                        BoxViewModel currentBox = new BoxViewModel();

                        currentBox.Compliment = currentBoxNode.SelectSingleNode("//compliment").InnerText;
                        currentBox.Description = currentBoxNode.SelectSingleNode("//description").InnerText;
                        currentBox.BoxType = currentBoxNode.SelectSingleNode("//boxtype").InnerText;
                        currentBox.InsideLength = decimal.Parse(currentBoxNode.SelectSingleNode("//il").InnerText);
                        currentBox.InsideBreadth = decimal.Parse(currentBoxNode.SelectSingleNode("//ib").InnerText);
                        currentBox.InsideHeight = decimal.Parse(currentBoxNode.SelectSingleNode("//ih").InnerText);
                        currentBox.OutsideLength = decimal.Parse(currentBoxNode.SelectSingleNode("//ol").InnerText);
                        currentBox.OutsideBreadth = decimal.Parse(currentBoxNode.SelectSingleNode("//ob").InnerText);
                        currentBox.OutsideHeight = decimal.Parse(currentBoxNode.SelectSingleNode("//oh").InnerText);
                        currentBox.BoxWeight = decimal.Parse(currentBoxNode.SelectSingleNode("//bw").InnerText);
                        currentBox.BoxGrossWeight = decimal.Parse(currentBoxNode.SelectSingleNode("//bgw").InnerText);
                        currentBox.BoxStrength = int.Parse(currentBoxNode.SelectSingleNode("//boxstrength").InnerText);

                        boxesList.Add(currentBox);
                    }

                }
                catch
                {
                    ViewBag.MsgText = "There was an error when processing the file!";
                    ViewBag.MsgColor = "Red";
                }

The problem I am experiencing here is that when I do it this way, every box is the same. It only gets the first box. The foreach loop is smart enough to know that there are two boxes, but it can't get the second box and add it to my list. Instead, I have a list of two of the same box.

I am willing to change almost anything about this to make it work. Any help would be greatly appreciated.

Upvotes: 0

Views: 1306

Answers (2)

BardMorgan
BardMorgan

Reputation: 454

Instead of using

XmlNodeList boxNodeList = xmlDoc.SelectSingleNode("//initialize/boxes").ChildNodes;

try using:

XmlNodeList boxNodeList = xmlDoc.SelectNodes("/initialize/boxes/box");

That should get you a node list of each box node.

Upvotes: 2

CoolBots
CoolBots

Reputation: 4889

You're referencing the root of the XML document, that's why only the data from the first element is being read. Get rid of the // in your call to SelectSingleNode:

            currentBox.Compliment = currentBoxNode.SelectSingleNode("compliment").InnerText;
            currentBox.Description = currentBoxNode.SelectSingleNode("description").InnerText;
            currentBox.BoxType = currentBoxNode.SelectSingleNode("boxtype").InnerText;
            currentBox.InsideLength = decimal.Parse(currentBoxNode.SelectSingleNode("il").InnerText);
            currentBox.InsideBreadth = decimal.Parse(currentBoxNode.SelectSingleNode("ib").InnerText);
            currentBox.InsideHeight = decimal.Parse(currentBoxNode.SelectSingleNode("ih").InnerText);
            currentBox.OutsideLength = decimal.Parse(currentBoxNode.SelectSingleNode("ol").InnerText);
            currentBox.OutsideBreadth = decimal.Parse(currentBoxNode.SelectSingleNode("ob").InnerText);
            currentBox.OutsideHeight = decimal.Parse(currentBoxNode.SelectSingleNode("oh").InnerText);
            currentBox.BoxWeight = decimal.Parse(currentBoxNode.SelectSingleNode("bw").InnerText);
            currentBox.BoxGrossWeight = decimal.Parse(currentBoxNode.SelectSingleNode("bgw").InnerText);
            currentBox.BoxStrength = int.Parse(currentBoxNode.SelectSingleNode("boxstrength").InnerText);

You can also use ./ to indicate current context:

currentBox.Compliment = currentBoxNode.SelectSingleNode("./compliment").InnerText;
...

Upvotes: 1

Related Questions