user2371290
user2371290

Reputation: 327

how to read xml files in C# ?

I have a code which reads an xml file. There are some parts I dont understand. From my understanding , the code will create an xml file with 2 elements, "Product" and "OtherDetails" . How come we only have to use writer.WriteEndElement(); once when we used writer.WriteStartElement twice ? , shouldn't we close each writer.WriteStartElement statement with a writer.WriteEndElement() statement ?

using System.Xml;

public class Program
{
    public static void Main()
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;

        XmlWriter writer = XmlWriter.Create("Products.xml", settings);
        writer.WriteStartDocument();
        writer.WriteComment("This file is generated by the program.");
        writer.WriteStartElement("Product");          // first s
        writer.WriteAttributeString("ID", "001");
        writer.WriteAttributeString("Name", "Soap"); 
        writer.WriteElementString("Price", "10.00")  

        // Second Element 
        writer.WriteStartElement("OtherDetails");
        writer.WriteElementString("BrandName", "X Soap");
        writer.WriteElementString("Manufacturer", "X Company");
        writer.WriteEndElement();
        writer.WriteEndDocument();

        writer.Flush();
        writer.Close();
    }
}
using System;
using System.Xml;

public class Program
{
    public static void Main()
    {
        XmlReader reader = XmlReader.Create("Products.xml");

        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element
            && reader.Name == "Product")
            {
                Console.WriteLine("ID = " + reader.GetAttribute(0));  
                Console.WriteLine("Name = " + reader.GetAttribute(1));

                while (reader.NodeType != XmlNodeType.EndElement)
                {
                    reader.Read();
                    if (reader.Name == "Price")
                    {
                        while (reader.NodeType != XmlNodeType.EndElement)
                        {
                            reader.Read();
                            if (reader.NodeType == XmlNodeType.Text)
                            {
                                Console.WriteLine("Price = {0:C}", Double.Parse(reader.Value));
                            }
                        }

                        reader.Read();

                    } //end if


                    if (reader.Name == "OtherDetails")
                    {
                        while (reader.NodeType != XmlNodeType.EndElement)
                        {
                            reader.Read();
                            if (reader.Name == "BrandName")
                            {
                                while (reader.NodeType != XmlNodeType.EndElement)
                                {
                                    reader.Read();
                                    if (reader.NodeType == XmlNodeType.Text)
                                    {
                                        Console.WriteLine("Brand Name = " + reader.Value);
                                    }
                                }
                                reader.Read();
                            } //end if

                            if (reader.Name == "Manufacturer")
                            {
                                while (reader.NodeType != XmlNodeType.EndElement)
                                {
                                    reader.Read();
                                    if (reader.NodeType == XmlNodeType.Text)
                                    {
                                        Console.WriteLine("Manufacturer = " + reader.Value);
                                    }
                                }

                            } //end if
                        }
                    } //end if
                } //end while
            } //end if

        } //end while
    }
}

I don't get this part:

if (reader.Name == "OtherDetails")
{
    while (reader.NodeType != XmlNodeType.EndElement)
    {
        reader.Read();
        if (reader.Name == "BrandName")
        {
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                reader.Read();
                if (reader.NodeType == XmlNodeType.Text)
                {
                    Console.WriteLine("Brand Name = " + reader.Value);
                }
            }

notice how the condition while (reader.NodeType != XmlNodeType.EndElement) has been used twice ?

why is that we don't have to specify

if (reader.NodeType == XmlNodeType.Element for OtherDetails) as we did for Product,

like this

if (reader.NodeType == XmlNodeType.Element
&& reader.Name == "OtherDetails")
{} 

Upvotes: 2

Views: 26131

Answers (3)

Deepak Kothari
Deepak Kothari

Reputation: 1763

Suppose if you want to read an xml file we need to use a dataset,because xml file internally converts into datatables using a dataset.Use the following line of code to access the file and to bind the dataset with the xml data.

    DataSet ds=new DataSet();
    ds.ReadXml(HttpContext.Current.Server.MapPath("~/Labels.xml");

DataSet comprises of many datatables,count of those datatables depends on number of Parent Child Tags in an xml file

Upvotes: 0

TekuConcept
TekuConcept

Reputation: 1284

If you need anything strait forward (no reading or research), here is what I did:

I recently wrote a custom XML parsing method for my MenuStrip for WinForms (it had hundreds of items and XML was my best bet).

// load the document
// I loaded mine from my C# resource file called TempResources
XDocument doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(TempResources.Menu)));

// get the root element
// (var is an auto token, it becomes what ever you assign it)
var elements = doc.Root.Elements();

// iterate through the child elements
foreach (XElement node in elements)
{
     // if you know the name of the attribute, you can call it
     // mine was 'name'
     // (if you don't know, you can call node.Attributes() - this has the name and value)
     Console.WriteLine("Loading list: {0}", node.Attribute("name").Value);

     // in my case, every child had additional children, and them the same
     // *.Cast<XElement>() would give me the array in a datatype I can work with
     // menu_recurse(...) is just a resursive helper method of mine
     menu_recurse(node.Elements().Cast<XElement>().ToArray()));
}

(My answer can also be found here: Reading an XML File With Linq - though it unfortunately is not Linq)

Upvotes: 0

Matthew Watson
Matthew Watson

Reputation: 109822

To answer your first question:

As the MSDN documentation for XmlWriter.WriteEndDocument() says:

Closes any open elements or attributes and puts the writer back in the Start state.

So it will automatically close any open elements for you. In fact, you can remove the call to WriteEndElement() altogether and it will still work ok.

And as people are saying in the comments above, you should perhaps consider using Linq-to-XML.

It can make things much easier. For example, to create the XML structure from your program using Linq-to-XML you can do this:

var doc = new XDocument(
    new XElement("Product",
            new XAttribute("ID", "001"), new XAttribute("Name", "Soap"),
        new XElement("Price", 10.01),
        new XElement("OtherDetails", 
            new XElement("BrandName", "X Soap"),
            new XElement("Manufacturer", "X Company"))));

File.WriteAllText("Products.xml", doc.ToString());

If you were reading data from the XML, you can use var doc = XDocument.Load("Filename.xml") to load the XML from a file, and then getting the data out is as simple as:

double price     = double.Parse(doc.Descendants("Price").Single().Value);
string brandName = doc.Descendants("BrandName").Single().Value;

Or alternatively (casting):

double price     = (double) doc.Descendants("Price").Single();
string brandName = (string) doc.Descendants("BrandName").Single();

(In case you're wondering how on earth we can cast an object of type XElement like that: It's because a load of explict conversion operators are defined for XElement.)

Upvotes: 3

Related Questions