xmlvb.netxmltextreader

XmlTextReader not working properly


I am trying to make a loop that reads an XML document for an item with a specific id number, and then stores the child nodes of this item as variables, which are then used to populate labels on my page.

Sub LinkButton_Click(sender As Object, e As CommandEventArgs)
    Dim selected = Convert.ToInt32(e.CommandArgument)
    System.Diagnostics.Debug.WriteLine("selected")
    System.Diagnostics.Debug.WriteLine (selected)

    Dim selectedXML = New XmlTextReader(MapPath("xml/questions.xml"))

    selectedXML.ReadToFollowing("Question")
    If selectedXML.HasAttributes Then
        selectedXML.MoveToNextAttribute()

        Do While selectedXML.MoveToNextAttribute()

            Dim compareID = selectedXML.Value
            System.Diagnostics.Debug.WriteLine("compareID:")
            System.Diagnostics.Debug.WriteLine(compareID)

            If compareID = selected Then
                selectedXML.ReadToFollowing("A")
                sA.Text = selectedXML.Value
                System.Diagnostics.Debug.WriteLine("SA:")
                System.Diagnostics.Debug.WriteLine(sA.Text)

                selectedXML.ReadToFollowing("Q")
                sQ.Text = selectedXML.Value
                System.Diagnostics.Debug.WriteLine("SQ:")
                System.Diagnostics.Debug.WriteLine(sQ.Text)

                selectedXML.ReadToFollowing("Download")
                sDL.Text = selectedXML.Value
                System.Diagnostics.Debug.WriteLine("SDL:")
                System.Diagnostics.Debug.WriteLine(sDL.Text)

                selectedXML.Close()
            Else
                selectedXML.ReadToNextSibling("Question")
            End If
        Loop
    Else
        System.Diagnostics.Debug.WriteLine("error")
        selectedXML.Close()
    End If

End Sub

XML Document (the redundant ID nodes are used in getting the ID number, but will eventually be eliminated. The current code only looks for the "id" attribute. This is possible because it is case sensitive)

<?xml version="1.0" encoding="utf-8" ?>
<Questions>

  <Question id="1">
    <ID>1</ID>
    <Category>Troubleshooting</Category>
    <Keywords>tags troubleshooting troubleshoot slow computer slowly</Keywords>
    <Q>Why is my computer so slow?</Q>
    <A>You have bad habits and your computer sucks</A>
    <Download>None.</Download>
  </Question>

  <Question id="2">
    <ID>2</ID>
    <Category>Troubleshooting</Category>
    <Keywords>tags troubleshooting troubleshoot slow computer slowly</Keywords>
    <Q>Why is my computer so slow? (again)</Q>
    <A>You have bad habits and your computer sucks</A>
    <Download>None.</Download>
  </Question>

  <Question id="3">
    <ID>3</ID>
    <Category>Microsoft Office</Category>
    <Keywords>tags microsoft office outlook calendar room rooms meeting schedule scheduling reserving reserve</Keywords>
    <Q>How do I reserve rooms and set up meetings?</Q>
    <A>View the following Document:</A>
    <Download><![CDATA[<a href="doc/new_employee/new_employee_agreement.doc">New Employee Software and Hardware Agreement</a>]]></Download>
  </Question>

</Questions>

A linkbutton passed the variable "selected" as a commandargument. In my console I can see that this is working correctly. ie, click the first item sccessfully sets "selected" to 1. Where I am having trouble is with reading the XML and passing the id attribute as the compareID variable. No matter what I do, I seem to always get compareID=0.

Secondly, the loop seems to be running indefinitely. How can I program the reader to stop when it reaches the end of the document after finding no matches.


Solution

  • Use Using Statement to automatically close the XmlReader even in the case of exceptions.

    Do not use XmlTextReader class, it is not recommended starting with the .NET Framework 2.0. Use XmlReader instead.

    Please note that we must turn to the nodes Q, A and Download in the order in which they are arranged in a xml-document.

    The simplified code:

    Using selectedXML = XmlReader.Create(MapPath("xml/questions.xml"))
        While selectedXML.ReadToFollowing("Question") ' Iterates through Question nodes.
    
            Dim compareID = selectedXML.GetAttribute("id")
    
            If compareID IsNot Nothing Then                
                Debug.WriteLine("compareID: " + compareID)
    
                If compareID = selected Then
                    selectedXML.ReadToFollowing("Q")
                    sQ.Text = selectedXML.ReadElementContentAsString
                    Debug.WriteLine("SQ: " + sQ.Text)
    
                    selectedXML.ReadToFollowing("A")
                    sA.Text = selectedXML.ReadElementContentAsString
                    Debug.WriteLine("SA: " + sA.Text)
    
                    selectedXML.ReadToFollowing("Download")
                    sDL.Text = selectedXML.ReadElementContentAsString
                    Debug.WriteLine("SDL: " + sDL.Text)
    
                    Exit While
                End If
            Else
                Debug.WriteLine("Error: attribute id not found")
            End If
    
        End While
    End Using ' Close XmlReader