Richard
Richard

Reputation: 529

Reading XML data using XmlDocument with C# - Reading attribute data and splitting the results

I'm trying to read some XML data using XmlDocument and having a few challenges.

My issues are as follows:

  1. When I try to get the bfihost value, it gives me the bfihost, propwet and saar element values combined as a single output. Why is this and how do I get just the bfihost?

  2. Each Depth element has an attribute named duration. My first foreach loop writes the string durationString to the console, but it doesn't seem to find any attributes called duration in the XmlNode chldNode.

  3. This issue is probably less important, but when I find the value for the element ReturnPeriods for example I can only retrieve all the values separated by commas. This isn't an issue as I've just used the Split(',') method and assigned it to an array and looped through that. I was curious if XmlDocument had a more elegant way of doing this?

Thanks for any help received.

Here is a stripped down version of the XML data. The , ... have been added as there is a lot more data in the actual xml file.

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<FEHCDROMExportedDescriptors appVersion="2.0.0.0" version="2.0.1">
    <PointDescriptors y="111111" x="222222" grid="GB">
        <bfihost>0.386</bfihost>
        <propwet>0.3</propwet>
        <saar>643</saar>
    </PointDescriptors>
    <PointDDF2013Values>
        <ReturnPeriods>
            <![CDATA[
                1.3, 1.58, 2, ...
            ]]>
        </ReturnPeriods>
        <Depths duration="0.083">
            <![CDATA[
                3.27693489525396, 3.98688804941076, 4.68688804941076, ...
            ]]>
        </Depths>
        <Depths duration="0.25">
            <![CDATA[
                5.37693489525396, 6.51484587430874, 7.81484587430874, ...
            ]]>
        </Depths>
        <Depths duration="0.5">
            <![CDATA[
                6.87693489525396, 8.38688804941076, 10.0017339237195, ...
            ]]>
        </Depths>
    </PointDDF2013Values>
</FEHCDROMExportedDescriptors>

The code I have written is as follows:

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(file);

            XmlTextReader reader = new XmlTextReader(file);
            XmlNode node = xmlDoc.ReadNode(reader);

            string durationString;
            foreach (XmlNode chldNode in node.ChildNodes)
            {
                //Read the attribute duration
                if (chldNode.Name == "Depths")
                {
                    if (chldNode.HasChildNodes)
                    {
                        foreach (XmlNode item in node.ChildNodes)
                        {
                            durationString = chldNode.Attributes["duration"].Value;
                            Console.WriteLine("durations[]: " + durationString);

                        }
                    }
                }
            }


            XmlNodeList pointDescriptors = xmlDoc.GetElementsByTagName("PointDescriptors");
            XmlElement xmlElement = (XmlElement)pointDescriptors[0];

            // Get coordinates
            XmlAttribute y = xmlElement.GetAttributeNode("y");
            Console.WriteLine("y[]: " + y.InnerXml);
            XmlAttribute x = xmlElement.GetAttributeNode("x");
            Console.WriteLine("x[]: " + y.InnerXml);

            // for some reason returns the bfi Host, propwet and saar
            XmlNodeList bfihost = xmlDoc.GetElementsByTagName("bfihost");
            Console.WriteLine("bfihost[]: " + pointDescriptors[0].InnerText);

            // returns all return periods as a string.
            XmlNodeList returnPeriods = xmlDoc.GetElementsByTagName("ReturnPeriods");
            //Console.WriteLine("Return Periods[]: " + returnPeriods[0].InnerText);

            //I can split the string by commas and remove white spaces as follows
            string[] returnPeriodsArray = returnPeriods[0].InnerText.Split(',').Select(sValue => sValue.Trim()).ToArray();
            foreach (string s in returnPeriodsArray)
            {
                //System.Console.Write("{0} ", s);
            }

            int k = 0;
            //Loop through all the depths, and split the results
            XmlNodeList depths = xmlDoc.GetElementsByTagName("Depths");
            XmlAttribute duration;
            for (int i = 0; i < depths.Count; i++)
            {
                if (depths[i].InnerText.Length > 0)
                {
                    
                    System.Console.Write("{0} ", "\n\n" + "Depth xxx" + "\n\n");
                    string[] depthsArray = depths[i].InnerText.Split(',').Select(sValue => sValue.Trim()).ToArray();
                    foreach (string s in depthsArray)
                    {
                        System.Console.Write("{0} ", "(" + returnPeriodsArray[k] + ") - " + s + "\n");
                        k++;
                        if (k > 21)
                        {
                            k = 0;
                        }
                    }
                
                }
            }

And the output I get is:

y[]: 11111 //correct
x[]: 22222 //correct
bfihost[]: 0.3860.3643 //this is combination of three elements for some reason?

///Here I try to get the depth data but nothing is returned.

Depth xxx // xxx is just a place holder until I can fix the above issue.

 (1.3) - 3.27693489525396 //all these outputs are correct.
 (1.58) - 3.98688804941076
 (2) - 4.68688804941076


Depth xxx

 (1.3) - 5.37693489525396
 (1.58) - 6.51484587430874
 (2) - 7.81484587430874



Depth xxx

 (1.3) - 6.87693489525396
 (1.58) - 8.38688804941076
 (2) - 10.0017339237195

Upvotes: 0

Views: 543

Answers (1)

Yitzhak Khabinsky
Yitzhak Khabinsky

Reputation: 22275

It is better to use LINQ to XML API. It is available in the .Net Framework since 2007.

c#

void Main()
{
    const string fileName = @"e:\Temp\FEHCDROME.xml";
    XDocument xdoc = XDocument.Load(fileName);
    
    XElement xelem = xdoc.Descendants("PointDescriptors").FirstOrDefault();

    Console.WriteLine("PointDescriptors:");
    Console.WriteLine("y[]: {0}", xelem.Attribute("y").Value);
    Console.WriteLine("x[]: {0}", xelem.Attribute("x").Value);
    Console.WriteLine("bfihost[]: {0}", xelem.Element("bfihost").Value);

    XElement rp = xdoc.Descendants("ReturnPeriods").FirstOrDefault();
    Console.WriteLine("{0}ReturnPeriods:", Environment.NewLine);
    foreach (string s in rp.Value.Split(',').Select(sValue => sValue.Trim()).ToArray())
    {
        Console.WriteLine("{0} ", s);
    }

    Console.WriteLine("{0}Depths:", Environment.NewLine);
    foreach (XElement dp in xdoc.Descendants("Depths"))
    {
        foreach (string s in dp.Value.Split(',').Select(sValue => sValue.Trim()).ToArray())
        {
            Console.WriteLine("{0} ", s);
        }
    }
}

Output

PointDescriptors:
y[]: 111111
x[]: 222222
bfihost[]: 0.386

ReturnPeriods:
1.3 
1.58 
2 
... 

Depths:
3.27693489525396 
3.98688804941076 
4.68688804941076 
... 
5.37693489525396 
6.51484587430874 
7.81484587430874 
... 
6.87693489525396 
8.38688804941076 
10.0017339237195 
... 

Upvotes: 1

Related Questions