ana steele
ana steele

Reputation: 45

How to Parse XML Where Child Nodes Have The Same Name

I have an XML file that I am parsing through and have come across a specific element that has it's own child nodes. The XML file is below:

<status.AppleSettings>
    <AppleInstance MaxCost="250" Status="77" NewMode="5" SharePrice="350"
                   FlagTF="False" TimeClock="0" TimeClockSec="14"
                   Options="7532890" ID="JK_7755" Owner="SLP90"
                   Server="PA.SL90.COL" Name="SLP90" GroupName="COL.PA"
                   Instance="AppleServiceInstance" NewFlag="True" FinalCount="0"/>
    <AppleInstance MaxCost="5" Status="0" NewMode="1" SharePrice="0"
                   FlagTF="False" TimeClock="300" TimeClockSec="1000"
                   Options="56794577431" Owner="A.CON" Instance="SL91"
                   NewFlag="True" FinalCount="1" List="1450, 1430"
                   Keyrepo="SYSTEMSERVER_7671902"/>
</status.AppleSettings>

As you can see, there's a parent node - AppleSettings and then two child nodes w/ the same name - AppleInstance. I created two separate classes for the child nodes since they have different attributes. I am able to access AppleSettings and when I do a quickwatch I can see the two child nodes inside, I just can't figure out how to access them. New to XML parsing and C# so everything is trial and error, learning a lot from stackoverflow.

Here is the code I have to access the AppleSettings parent node:

    private List<Data> GetAppleSettingsNode(List<XmlDocument> XMLdocument, List<Data> DataList)
    {
        for (int i = 0; i < XMLdocument.Count(); i++)
        {
              AppleSettings temp = new AppleSettings();

              var temp2 = XMLdocument[i].DocumentElement.SelectNodes("//AppleSettings");
              foreach (var node in temp2)
             {
                var temp3 = node.ToString();
             }

              XmlNode xmlNode1 = XMLdocument[i].SelectSingleNode("//AppleSettings");

              XmlSerializer serial1 = new XmlSerializer(typeof(AppleSettings));

              temp = (AppleSettings)serial1.Deserialize(new XmlNodeReader(xmlNode1));
         }
     }

Is it even necessry to access the AppleSettings node? Could I go directly to the two AppleInstance child nodes? If someone could help me out, I'd appreciate it. Thanks!

Upvotes: 1

Views: 1317

Answers (3)

Mirzan
Mirzan

Reputation: 94

The i of LargeXMLResponse[i] is loop count of the Large XML response if your response tag in wrapped up in between, and if you have a alternative way please go ahead with.

var ResponseToList = LargeXMLResponse[i].Descendants("Response").ToList();

if (ResponseToList.Count() > 0){

for (var pf = 0; pf < ResponseToList.Count(); pf++)
{
ResponseInfoList.Add(new ResponseToList{

id = ResponseToList[pf].Descendants("Block").Attributes("id").Count() > 0 ? 

ResponseToList[pf].Descendants("Block ").Attributes("id").First().Value : "",

});
}
}

Upvotes: 0

jdweng
jdweng

Reputation: 34421

Try following :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication8
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(Root));
            Root root = (Root)serializer.Deserialize(reader);

        }

    }

    public class Root
    {
        [XmlArray("status.AppleSettings")]
        [XmlArrayItem("AppleInstance")]
        public List<ApppleInstance> AppleInstances { get; set; } 
    }
    public class ApppleInstance
    {
        [XmlAttribute()]
        public int MaxCost { get; set; }
        [XmlAttribute()]
        public int Status { get; set; }
        [XmlAttribute()]
        public int NewMode { get; set; }

        [XmlAttribute()]
        public int SharePrice { get; set; }

        private Boolean _FlagTF { get; set; }
        [XmlAttribute()]
        public string FlagTF 
        { 
            get { return _FlagTF? "True" : "False";}
            set { _FlagTF = (value == "True") ? true : false;}
        }
        [XmlAttribute()]
        public int TimeClock { get; set; }
        [XmlAttribute()]
        public int TimeClockSec { get; set; }
        [XmlAttribute()]
        public long Options { get; set; }
        [XmlAttribute()]
        public string ID { get; set; }
        [XmlAttribute()]
        public string Owner { get; set; }
        [XmlAttribute()]
        public string Server { get; set; }
        [XmlAttribute()]
        public string Name { get; set; }
        [XmlAttribute()]
        public string GroupName { get; set; }
        [XmlAttribute()]
        public string Instance { get; set; }

        private Boolean _NewFlag { get; set; }
        [XmlAttribute()]
        public string NewFlag
        {
            get { return _NewFlag ? "True" : "False"; }
            set { _NewFlag = (value == "True") ? true : false; }
        }

        [XmlAttribute()]
        public int FinalCount { get; set; }

        private int[] _List { get; set; }
        [XmlAttribute()]
        public string List 
        {
            get { return string.Join(",",_List);}
            set { _List = value.Split(new char[] {','}).Select(x => int.Parse(x)).ToArray() ;}
        }
        [XmlAttribute()]
        public string Keyrepo { get; set; }
    }
}

Upvotes: 1

Yitzhak Khabinsky
Yitzhak Khabinsky

Reputation: 22157

It is better to use LINQ to XML API.

(1) The code below shows how to access any XML attribute by its name.

(2) .FirstOrDefault()?.Value technique will prevent exceptions generation when an attribute is missing.

c#

void Main()
{
    const string FILENAME = @"e:\Temp\AppleSettings.xml";

    XDocument doc = XDocument.Load(FILENAME);
    foreach (var el in doc.Descendants("AppleInstance"))
    {
        Console.WriteLine("MaxCost={0}", el.Attributes("MaxCost").FirstOrDefault()?.Value);
        Console.WriteLine("Instance={0}", el.Attributes("Instance").FirstOrDefault()?.Value);
        Console.WriteLine("GroupName={0}", el.Attributes("GroupName").FirstOrDefault()?.Value);
    }
}

Upvotes: 1

Related Questions