0

I am trying to parse the below Xml. It could have multiple invoice tags:

<Invoices>
    <Invoice>
        <Invoice_ID>1234</Invoice_Id>
        <Billing>
            <Name> abc </Name>
            <Address1>1 main street</Address1>
            <City> city </city>
            <State>State </State
            <Zip>00000</zip>
            <Amount>
                <BaseAmt>35</BaseAmt>
                <Tax>3</Tax>
                <Total>28<total>
            <Amount>
        </Billing>      
        <item>
                 <Name> pen </Name>
                 <qty> 5 </qty>
                 <amount> 10 </amount>
        </item> 
        <item>
            <Name> Paper </Name>
                 <qty> 3 </qty>
                 <amount> 20 </amount>
        </item>                                 
        </Invoice>
</Invoices>

Below is my code :

Dim xmlDoc As XmlDocument = New XmlDocument()
xmlDoc.Load(fileName)
Dim invNum As Integer = 0
Dim nodeLst As XmlNodeList = xmlDoc.SelectNodes("/Invoices/Invoice")
invNum = nodeLst.Count

For Each invDetail As XmlElement In nodeLst
    Dim invID As String = invDetail("Invoice_ID").InnerText.ToString()
Next

I need to get the value for the remaining tags i.e child nodes like Billing/Name , Billing/Name/Amount , Items/Items/Name

3
  • What problem are you having? Commented Sep 3, 2013 at 21:04
  • I got the invID using invDetail("Invoice_ID).InnerText but when I am trying to get the name like invDetail.SelectSingleNode("Billing/Name") it is giving me the error saying "Object reference not set to the instance of the object" Commented Sep 3, 2013 at 21:11
  • "Billing/Name" is not a name. You need SelectSingleNode("Billing"), then SelectSingleNode("Name") on that. Commented Sep 3, 2013 at 21:30

2 Answers 2

2

Two things need to be done to address this issue:

1.) Your XML is not well formed. Remember that XML is case sensitive, requires closing brackets, etc.; there are numerous errors in your XML above - specifically:

a. Open tag 'Invoice_ID' and close tag 'Invoice_Id' (should be <Invoice_ID> ... </Invoice_ID>).

b. Open tag 'City' and close tag 'city' (should be <City> ... </City>).

c. Element 'State' is missing a right angle bracket '>' on it's close tag (should be </State>).

d. Open tag 'Zip' and close tag 'zip' (should be <Zip> ... </Zip>).

e. Two open tags for 'Amount' (<Amount> ... <Amount>); should be open and close tag (<Amount> ... </Amount>).

f. You are missing a close tag for the first 'item' element. (add </item>).

g. Open tag 'Total' and close tag 'total' (should be <Total>...</Total>).

The fixed up XML will look like as follows:

<Invoices>
    <Invoice>
        <Invoice_ID>1234</Invoice_ID>
        <Billing>
            <Name> abc </Name>
            <Address1>1 main street</Address1>
            <City> city </City>
            <State>State </State>
            <Zip>00000</Zip>
            <Amount>
                <BaseAmt>35</BaseAmt>
                <Tax>3</Tax>
                <Total>28</Total>
            </Amount>
        </Billing>      
        <Items>
            <item>
                <Name> pen </Name>
                <qty> 5 </qty>
                <amount> 10 </amount>
            </item>
            <item>
                <Name> Paper </Name>
                <qty> 3 </qty>
                <amount> 20 </amount>
            </item>                                         
        </Items>
    </Invoice>
</Invoices>

2.) Once you have fixed up your XML, to select all 'Invoice' elements and access their child elements (such as 'Name', etc.) - you can first select all 'Invoice' elements and then iterate through each, accessing the child element InnertText/values you need as appropriate.

XmlNodeList nodeList = doc.SelectNodes("//Invoice");

foreach (XmlNode invoice in nodeList)
    Console.WriteLine(invoice.SelectSingleNode("Billing/Name").InnerText);

The output from the above would read:

abc

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

1

If you are simply accessing the value of a direct-child element, like Invoice_ID, you can use the indexer to access the child element by name, as you are already doing, like this:

invDetail("Invoice_ID")

However, if you want to go deeper to get the value of a lower descendant, you can use SelectSingleNode or SelectNodes to access the node via XPath. The XPath will be relative to the current node. For instance:

For Each invDetail As XmlElement In nodeLst
    Dim invID As String = invDetail("Invoice_ID").InnerText
    Dim name As String = invDetail.SelectSingleNode("Billing/Name").InnerText
    ' etc.
    For Each item As XmlElement In invDetail.SelectNodes("item")
        Dim itemName As String = item("Name").InnerText
        ' etc.
    Next
Next

9 Comments

I got the invID using invDetail("Invoice_ID).InnerText but when I am trying to get the name like invDetail.SelectSingleNode("Billing/Name") it is giving me the error saying "Object reference not set to the instance of the object"
I just tested it and that works for me. I updated my answer to show my code. There must be something else wrong with your code or your XML. If you can't figure it out, please update your question with an actual example of the XML that fails (the current example is not well-formed, so it's obviously not the real one you are testing against) and the exact code that fails.
Thanks Steven Doggart , I fixed that error and ableto get the value. I am unable to put the actual Xml due confidentiality reasons.One last thing I need help with is that in my above XMl you see items tag , how do I loop through them as I am already in the for each loop.
I added to my example to demonstrate how to do that.
I was missing upper case. Thanks a million ton for your help.I got all the data I was looking for.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.