How to loop XmlTextReader properly (C#)?

999 Views Asked by At

Below is a sample of the type of XML file I am trying to handle. If I have only one part along with an accompanying number/character I can process the data extraction without the necessity of the 'if (!reader.EOF)' control structure. However when I try to include this structure so that I can loop back to checking for another part, number, and character group, it deadlocks.

Any advice as to how to do this properly? This was the most efficient idea that popped into my head. I am new to reading data from XMLs.

Sample Xml:

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <part>100B</part>
  <number>45</number>
  <character>a</character>

  <part>100C</part>
  <number>55</number>
  <character>b</character>
</note>

Code:

String part = "part";
String number = "number";
String character = "character";
String appendString = "";
StringBuilder sb = new StringBuilder();

try
{
    XmlTextReader reader = new XmlTextReader("myPath");
    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element: // The node is an element.

                myLabel:
                if (reader.Name == part)
                {
                    part = reader.ReadInnerXml();
                }
                if (reader.Name == number)
                {
                    number = reader.ReadInnerXml();
                    number = double.Parse(number).ToString("F2"); //format num
                }
                if (reader.Name == character)
                {
                    character = reader.ReadInnerXml();
                }

                //new string
                appendString = ("Part: " + part + "\nNumber: " + number +
 "\nCharacter: " + character + "\n");

                //concatenate
                sb.AppendLine(appendString);

                if (reader.EOF != true)
                {
                    Debug.Log("!eof");
                    part = "part";
                    number = "number";
                    character = "character";
                    goto myLabel;
                }

                //print fully concatenated result
                sb.ToString();

                //reset string builder
                sb.Length = 0;

                break;
        }
    }
}
catch (XmlException e)
{
    // Write error.
    Debug.Log(e.Message);
}
catch (FileNotFoundException e)
{
    // Write error.
    Debug.Log(e);
}
catch(ArgumentException e)
{
    // Write error.
    Debug.Log(e);
}
2

There are 2 best solutions below

3
Alexander Petrov On BEST ANSWER

XmlReader class has many useful methods. Use it.

See this:

var sb = new StringBuilder();

using (var reader = XmlReader.Create("test.xml"))
{
    while (reader.ReadToFollowing("part"))
    {
        var part = reader.ReadElementContentAsString();
        sb.Append("Part: ").AppendLine(part);

        reader.ReadToFollowing("number");
        var number = reader.ReadElementContentAsDouble();
        sb.Append("Number: ").Append(number).AppendLine();

        reader.ReadToFollowing("character");
        var character = reader.ReadElementContentAsString();
        sb.Append("Character: ").AppendLine(character);
    }
}

Console.WriteLine(sb);
0
Alexan On

Alexander's answer is fine, I just want to add sample using XDocument, according comments of Jon Skeet:

var sb = new StringBuilder();
var note = XDocument.Load("test.xml").Root.Descendants();            
foreach (var el in note)
{                
    sb.Append(el.Name).Append(": ").AppendLine(el.Value);               
}
Console.WriteLine(sb);