Take the 2-minute tour ×

I have an xml formatted document that looks like this:

< Recipe>
  < Entry name="Stuffed Red Cabbage" ethnicity="Slavic" />
  < Cook_Time Hrs="1" Mins="30" />
  < Ingredients>
              < Cabbage Amount="1" Measurement="head" />
              < Egg Amount="1" Measurement="unit" />
              < Ground_Beef Amount="1" Measurement="lb" />
              < Margarine Amount="1/2" Measurement="cup" />
              < Onion Amount="1" Measurement="unit" />
              < Rice Amount="1" Measurement="cup" />
              < Tomato_Soup Amount="3" Measurement="cans" />
  < /Ingredients>
  < Description>core cabbage and boil until leaves start pulling away. Strip leaves and let cool.
chop onion and place in frying pan with margarine and heat till lightly browned.
put ground beef, rice, onion, egg and salt to taste in bowl and mix.
stuff each leaf with mixture.
put tomato soup and stuffed leaves in pot and cook for about an hour.</Description>

and I have code that so far looks like this:

OpenFileDialog1.Filter = "RecipeBook files (*.rcp)|*.rcp"
    If OpenFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
            Dim settings As New XmlReaderSettings()
            settings.IgnoreComments = True
            Dim RecipeCard As String = OpenFileDialog1.FileName
                            Dim xmlreader As XmlTextReader
            xmlreader = New XmlTextReader(RecipeCard)
            Do While xmlreader.Read
                'needs to read xml and write appropriate items to database and listview
                If xmlreader.Name.Equals("Entry") Then
                    MessageBox.Show(xmlreader.GetAttribute("name") & " " & xmlreader.GetAttribute("ethnicity"), "test")
                End If
                If xmlreader.Name.Equals("Cook_Time") Then
                    MessageBox.Show(xmlreader.GetAttribute("Hrs") & " hrs " & xmlreader.GetAttribute("Mins") & " mins", "test")
                End If
                If xmlreader.Name.Equals("Ingredients") Then

                End If
        End Try
    End If

My question has to do with parsing the Ingredients section. I was planning on doing something like this:

Dim IngredientCount As Integer = 0
Dim count As Integer = (something here that gets the count of subelements inside the Ingredients element)
                    For i = 1 To count
                    MessageBox.Show(xmlreader.GetAttribute("Amount") & " " & xmlreader.GetAttribute("Measurement"), "test")

I just can't figure out how to get the number of subelements and then how to refer to each one in succession to get the name and then the attributes of that subelement. Any suggestions would be greatly appreciated.

share|improve this question
Are you using .net 3.5? Xlinq will make that much easier. msdn.microsoft.com/en-us/vbasic/bb738050.aspx –  Jace Rhea Dec 12 '09 at 19:58
I am using 3.5, and I need to reuse this for 3.5 compact as well, I'll take a look at that. –  MaQleod Dec 12 '09 at 20:02
add comment

3 Answers

up vote 1 down vote accepted

If you want to use the XmlTextReader then you can solve your problem by using ReadSubtree:

If xmlreader.Name.Equals("Ingredients") Then
    Dim inner As XmlReader
    inner = xmlreader.ReadSubtree()
    While inner.Read
        If inner.IsStartElement Then
            MessageBox.Show(inner.GetAttribute("Amount") & " " & inner.GetAttribute("Measurement"), "test")
         End If
    End While
End If

It'd be easier though to not use XmlTextReader and instead use Linq to XML.

share|improve this answer
This option worked the best for everything I had in place already. It isn't the most efficient as far as memory goes, but it was the easiest to implement. –  MaQleod Dec 13 '09 at 23:14
add comment

One of your comments indicates you are using the 3.5 framework. If so then you can take advantage of XML literals to get your solution.

Dim data = XDocument.Load(xmlReader)
Dim count = data.<Ingredients>.Elements().Count()
share|improve this answer
Thaaaaaank you for eventually using XML literals ... Nobody seems to know or use them ;) +1 –  Dario Dec 12 '09 at 20:29
add comment

What I've done for this in the past is call Read() to get each subelement in turn. After each Read(), check that it's a start element. If it's not a start element then you've reached the end of the enclosing Ingredient tag and it's time to read the next one. The sample code in this documentation might be helpful:


XmlReader cannot give you the number of subelements of the current element because it reads one tag at a time. It hasn't read those other elements yet so it doesn't know how many there are. If you want to get more info on the XML tree while you're reading it, use XmlDocument. However, XmlDocument will read the whole file into memory at once before you even start processing it, whereas XmlReader reads the file from start to finish as you process it. XmlReader should be faster and more memory-efficient.

The sample here shows how to iterate over attributes if you don't know ahead of time which attributes an element will have:


share|improve this answer
add comment

Your Answer


