0

I have the following code

XmlDocument doc = new XmlDocument();
doc.Load(xmlFileName);

XmlNode deeperNodes = 
        doc.DocumentElement.ChildNodes[11].ChildNodes[1].ChildNodes[3].ChildNodes[1].ChildNodes[2];
XmlNode deeperetNodes = 
        doc.DocumentElement.ChildNodes[11].ChildNodes[1].ChildNodes[3].ChildNodes[1].ChildNodes[3];

string firstValue = deeperNodes.Attributes["count"].Value.ToString();
string secondValue = deeperetNodes.Attributes["count"].Value.ToString();

The XML I am reading is to a given standard so is always the correct. Is there a better more robust way to read the values?

Update: Sample Xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Rn>
    <Te>Fort</Te>
    <Th></Th>
    <Lh>c</Lh>
    <Fe>C</Fe>
    <Ue></Ue>
    <RS></RS>
    <RS></RS>
    <RS></RS>
    <RS> </RS>
    <RS></RS>
    <RS></RS>
    <RS>
        <Tl>New</Tl>
        <SS>
            <Tl>New</Tl>
            <Description>A</Description>
            <Text>The</Text>
            <IssueListing>
                <Refinement></Refinement>
                <Chart ce="p">
                    <Axis>New</Axis>
                    <MajorAttribute>Anal</MajorAttribute>
                    <GroupingSection count="38">
                        <groupTl>Is</groupTl>
                    </GroupingSection>
                    <GroupingSection count="364">
                        <groupTl>Is</groupTl>
                    </GroupingSection>
                </Chart>
            </IssueListing>
        </SS>
    </RS>
</Rn>
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • 6
    This is a really fragile way to parse xml, given that it is using indices and also conveying nothing about the intention to the next developer. Can you please post an example of the `xml` document so that we can assist with more robust xpath. – StuartLC Oct 23 '14 at 10:36
  • 3
    Do you need to use XmlDocument? While not *directly* related to the question, LINQ to XML is generally much simpler... if we knew that was an option, answers could use that. – Jon Skeet Oct 23 '14 at 10:38
  • if the xml document structure is to a given standard, then you can create model classes for it and load it with Deserialize class. Cleanest way for my. some info here: http://msdn.microsoft.com/en-us/library/4abbf6k0(v=vs.110).aspx – vidriduch Oct 23 '14 at 10:44
  • Look at [this answer](http://stackoverflow.com/questions/364253/how-to-deserialize-xml-document) on a good take on deserializing – Allmighty Oct 23 '14 at 11:03
  • Hi Stuart, that is my big issue its very unreadable. I am not tied to XmlDocument just whatever works and can be considered best practive. – user3805235 Oct 23 '14 at 14:36
  • FortcC NewNewAThe NewAnalIs Is – user3805235 Oct 23 '14 at 15:03
  • Am I missing something or could you maybe just use XPath looking for `GroupingSection`? – John Bustos Oct 23 '14 at 15:29

1 Answers1

1

Here's some ideas on more robust parsing, using XPath. The idea here is to latch onto an element of interest, which I've taken to be the Chart element with attribute ce with a value of 'p', and then use this as a frame of reference. Also, unless the Xml has been validated (e.g. vs an XSD), don't assume that elements exist or are valid, so check for nulls, invalid data types, etc.

XmlDocument with XPath version:

var doc = new XmlDocument();
doc.LoadXml(xmlFileName);

int firstValue, secondValue;
var interestingChartNode = doc.SelectSingleNode("//Chart[@ce='p']");
if (interestingChartNode != null)
{
    firstValue = Convert.ToInt32(interestingChartNode
                                 .SelectSingleNode("GroupingSection[1]/@count").Value);
    secondValue = Convert.ToInt32(interestingChartNode
                                 .SelectSingleNode("GroupingSection[2]/@count").Value);
}

Alternatively, Linq to Xml
(Personally I would still skip over all the ignored nodes with XPath, but others may disagree):

var xdoc = XDocument.Parse(xmlFileName); // using System.Xml.Linq;
var interestingGroupingSections = xdoc
         .XPathSelectElements("//Chart[@ce='p']/GroupingSection"); // using System.Xml.XPath;
if (interestingGroupingSections.Any())
{
    firstValue = Convert.ToInt32(interestingGroupingSections.First()
       .Attributes("count")
       .First().Value);
    secondValue = Convert.ToInt32(interestingGroupingSections.Skip(1)
       .Attributes("count")
       .First().Value);
}
StuartLC
  • 104,537
  • 17
  • 209
  • 285