Search code examples
c#xmlxmlreader

xml attributes not being detected


I'm having some trouble with my c# application. It's only able to get the attributes of the first node and then it can't get the following node's attributes.

The XML is in this format..

<ALLPRODUCTS>
  <PRODUCT ITEM="1">
     <QUANTITY>5</QUANTITY>
  </PRODUCT>
  <PRODUCT ITEM="2">
     <QUANTITY>6</QUANTITY>
  </PRODUCT>....

The application gets the first product number as 1 and it has a quantity of 5... but after that it just gives the quantities and says the item number is null. Here is the code im using...

 while (reader.Read())
        {
            if (reader.Name.Equals("PRODUCT"))
            {
                String id;
                String qty;                

                try
                {

                    id = reader.GetAttribute("ITEM");
                    reader.ReadToFollowing("QUANTITY");
                    qty = reader.ReadInnerXml();

                    if (qty.Equals("0"))
                    {
                        oos++;
                    }
                    else
                    {
                        inStock++;
                    }

                    status.Refresh();
                    stockLevelList.Add(id, qty);

                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message, e.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }

Can anyone suggest why the products after the first one are getting null as id?


Solution

  • You are not checking if the reader is at the beginning of the element. Your code is blowing up because it is trying to process based on the end element of PRODUCT.

    Add this check just after the if statement where it is checking for "PRODUCT".

    if (reader.Name.Equals("PRODUCT"))
    {
        if (!reader.IsStartElement())
            continue;
    
        // Your normal processing code here.
    }
    

    This is what makes using the XmlReader somewhat of a pain. It traverses every single element which means you need to pay attention to where it could be. The first time through, it is at the Start Element. You process and everything is good, but then it reaches the </PRODUCT> element which is still named "PRODUCT" and that's where it falls apart.

    Below is the order based on your code of moving the reader forward.

    • reader.Read() moves to the first element: ALLPRODUCTS
    • Not what you were looking for so reader.Read() again and it finds node type Whitespace because there is no inner text.
    • reader.Read() moved to PRODUCT
    • You get an attribute and then tell it to read to QUANTITY. (Note you cannot go back. Order matters)
    • reader.Read() moves to the next element PRODUCT. This is not <PRODUCT>. It is </PRODUCT>.
    • Your code now begins most of the above process again, but fails because it was not on <PRODUCT>

    EDIT: Also becareful with XmlReader. The XML doesn't necessarily have to be valid in order for XmlReader to work up to a certain point. It will only throw an error once it reaches an issue and you may have already processed several hundred nodes at that point.