XML Parsing - Read a Simple XML File and Retrieve Values

113,330

Solution 1

Easy way to parse the xml is to use the LINQ to XML

for example you have the following xml file

<library>
    <track id="1" genre="Rap" time="3:24">
        <name>Who We Be RMX (feat. 2Pac)</name>
        <artist>DMX</artist>
        <album>The Dogz Mixtape: Who's Next?!</album>
    </track>
    <track id="2" genre="Rap" time="5:06">
        <name>Angel (ft. Regina Bell)</name>
        <artist>DMX</artist>
        <album>...And Then There Was X</album>
    </track>
    <track id="3" genre="Break Beat" time="6:16">
        <name>Dreaming Your Dreams</name>
        <artist>Hybrid</artist>
        <album>Wide Angle</album>
    </track>
    <track id="4" genre="Break Beat" time="9:38">
        <name>Finished Symphony</name>
        <artist>Hybrid</artist>
        <album>Wide Angle</album>
    </track>
<library>

For reading this file, you can use the following code:

public void Read(string  fileName)
{
    XDocument doc = XDocument.Load(fileName);

    foreach (XElement el in doc.Root.Elements())
    {
        Console.WriteLine("{0} {1}", el.Name, el.Attribute("id").Value);
        Console.WriteLine("  Attributes:");
        foreach (XAttribute attr in el.Attributes())
            Console.WriteLine("    {0}", attr);
        Console.WriteLine("  Elements:");

        foreach (XElement element in el.Elements())
            Console.WriteLine("    {0}: {1}", element.Name, element.Value);
    }
}

Solution 2

I usually use XmlDocument for this. The interface is pretty straight forward:

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

You can access nodes similar to a dictionary:

var tasks = doc["Tasks"];

and loop over all children of a node.

Solution 3

Are you familiar with the DataSet class?

The DataSet can also load XML documents and you may find it easier to iterate.

http://msdn.microsoft.com/en-us/library/system.data.dataset.readxml.aspx

DataSet dt = new DataSet();
dt.ReadXml(@"c:\test.xml");

Solution 4

Try XmlSerialization

try this

[Serializable]
public class Task
{
    public string Name{get; set;}
    public string Location {get; set;}
    public string Arguments {get; set;}
    public DateTime RunWhen {get; set;}
}

public void WriteXMl(Task task)
{
    XmlSerializer serializer;
    serializer = new XmlSerializer(typeof(Task));

    MemoryStream stream = new MemoryStream();

    StreamWriter writer = new StreamWriter(stream, Encoding.Unicode);
    serializer.Serialize(writer, task);

    int count = (int)stream.Length;

     byte[] arr = new byte[count];
     stream.Seek(0, SeekOrigin.Begin);

     stream.Read(arr, 0, count);

     using (BinaryWriter binWriter=new BinaryWriter(File.Open(@"C:\Temp\Task.xml", FileMode.Create)))
     {
         binWriter.Write(arr);
     }
 }

 public Task GetTask()
 {
     StreamReader stream = new StreamReader(@"C:\Temp\Task.xml", Encoding.Unicode);
     return (Task)serializer.Deserialize(stream);
 }
Share:
113,330
Lucidity
Author by

Lucidity

Updated on July 18, 2020

Comments

  • Lucidity
    Lucidity almost 4 years

    I've written a Task Scheduling program for learning purposes. Currently I'm saving the scheduled tasks just as plain text and then parsing it using Regex. This looks messy (code wise) and is not very coherent.

    I would like to load the scheduled tasks from an XML file instead, I've searched quite a bit to find some solutions but I couldn't get it to work how I wanted.

    I wrote an XML file structured like this to store my data in:

    <Tasks>
        <Task>
            <Name>Shutdown</Name>
            <Location>C:/WINDOWS/system32/shutdown.exe</Location>
            <Arguments>-s -f -t 30</Arguments>
            <RunWhen>
                <Time>8:00:00 a.m.</Time>
                <Date>18/03/2011</Date>
                <Days>
                    <Monday>false</Monday>
                    <Tuesday>false</Tuesday>
                    <Wednesday>false</Wednesday>
                    <Thursday>false</Thursday>
                    <Friday>false</Friday>
                    <Saturday>false</Saturday>
                    <Sunday>false</Sunday>
                    <Everyday>true</Everyday>
                    <RunOnce>false</RunOnce>
                </Days>
            </RunWhen>
            <Enabled>true</Enabled>
        </Task>
    </Tasks>
    

    The way I'd like to parse the data is like so:

    1. Open Tasks.xml
    2. Load the first Task tag.
    3. In that task retrieve the values of the Name, Location and Arguments tags.
    4. Then open the RunWhen tag and retrieve the values of the Time and Date tags.
    5. After that open the Days tag and retrieve the value of each individual tag within.
    6. Retrieve the value of Enabled.
    7. Load the next task and repeat steps 3 -> 7 until all the Task tags in Tasks have been parsed.

    I'm very sure you can do it this way I just can't work it out as there are so many different ways to do things in XML I got a bit overwhelmed. But what I've go so far is that I would most likely be using XPathDocument and XPathNodeIterator right?

    If someone can show me an example or explain to me how this would be done I would be very happy.

  • John Saunders
    John Saunders about 11 years
    -1: DataTable cannot load all XML, only XML that matches the pattern of a relational database.
  • WraithNath
    WraithNath about 11 years
    @JohnSaunders - Care to elaborate? I just tried the above code with the xml file in question and reads it no problem
  • John Saunders
    John Saunders about 11 years
    Just what I said. DataSet can't handle arbitrary XML. It can only handle XML that maps to a "relational" structure. Many "normal" things you might want to use with XML won't work with DataSet. For instance, <root><parent1><child/></parent1><parent2><child/></parent2>‌​</root>. A relational table can't have two parents, so this won't work with DataSet.
  • WraithNath
    WraithNath about 11 years
    @JohnSaunders - Thanks, so although it works for the above xml, it might not work when there are multiple different tasks (full xml file). will have to try and remember that if I run into problems using it again in the future
  • VenerableAgents
    VenerableAgents about 9 years
    For those who want to copy/paste this code, you'll also need to add "using System.Xml.Linq;"
  • Moeez
    Moeez about 5 years
    Can you please see one of my question regarding the xml response?
  • Moeez
    Moeez about 5 years
    Can you please see one of my question regarding the xml response?