Search code examples
xmlvb.netxml-parsingxmlreader

VB.NET reading XML file troubles


I am using the following code to parse a XML file of mine:

Dim xml As String = "<?xml version=""1.0"" encoding=""Windows-1252""?>" & _
                        "<theref:theref-msg xmlns:csr=""http://www.xxxxx.com/Schema/csr"" xmlns:theref=""http://www.xxxxx.com/Schema/theref"">" & _
                          "<theref:header>" & _
                            "<theref:eid />" & _
                            "<theref:reference_id>429</theref:reference_id>" & _
                            "<theref:sr_type_code>US1</theref:sr_type_code>" & _
                            "<theref:event_type_code>REQUEST</theref:event_type_code>" & _
                            "<theref:eai_event_code>DSR</theref:eai_event_code>" & _
                            "<theref:source_code>WORKS</theref:source_code>" & _
                            "<theref:target_code>APP</theref:target_code>" & _
                            "<theref:status_code />" & _
                            "<theref:details />" & _
                          "</theref:header>" & _
                        "</theref:theref-msg>"

    Dim document As XDocument = XDocument.Parse(xml)

    Dim pupils = From pupil In document.Descendants("theref:theref-msg") _
                 Select New With _
                 { _
                    .Name = pupil.Element("theref:reference_id").Value, _
                    .TagID = pupil.Element("theref:sr_type_code").Value _
                 }

    For Each pupil In pupils
        Debug.Print("{0}: {1}", pupil.Name, pupil.TagID)
    Next

The problem being is that it doesn't seem to work at all. It crashes on the line:

Dim pupils = From pupil In document.Descendants("csreai:csreai-msg") _
                 Select New With _
                 { _
                    .Name = pupil.Element("csreai:reference_id").Value, _
                    .TagID = pupil.Element("csreai:sr_type_code").Value _
                 }

ERROR is: A first chance exception of type 'System.Xml.XmlException' occurred in System.Xml.dll

A first chance exception of type 'System.Xml.XmlException' occurred in System.Xml.dll The ':' character, hexadecimal value 0x3A, cannot be included in a name. 5

UPDATED CODE:

Dim xml As String = "<?xml version=""1.0"" encoding=""Windows-1252""?>" & _
                    "<theref:theref-msg xmlns:csr=""http://www.xxxxx.com/Schema/csr"" xmlns:theref=""http://www.xxxxx.com/Schema/theref"">" & _
                      "<theref:header>" & _
                        "<theref:eid />" & _
                        "<theref:reference_id>429</theref:reference_id>" & _
                        "<theref:sr_type_code>US1</theref:sr_type_code>" & _
                        "<theref:event_type_code>REQUEST</theref:event_type_code>" & _
                        "<theref:eai_event_code>DSR</theref:eai_event_code>" & _
                        "<theref:source_code>WORKS</theref:source_code>" & _
                        "<theref:target_code>APP</theref:target_code>" & _
                        "<theref:status_code />" & _
                        "<theref:details />" & _
                      "</theref:header>" & _
                      "<theref:body>" & _
                        "<csr:document>" & _
                          "<csr:header>" & _
                            "<csr:system>CSR</csr:system>" & _
                            "<csr:doc_name>FULLSR</csr:doc_name>" & _
                            "<csr:version>3.1</csr:version>" & _
                            "<csr:dml_event>UPDATE</csr:dml_event>" & _
                          "</csr:header>" & _
                    "</csr:document></theref:body></theref:theref-msg>"

Dim xmlb = From getXMLData In document.<theref:theref-msg>.<theref:header>.<theref:body>.<csr:document>.<csr:header>

Newest UPDATE

What if i have this:

   <csr:custom_attributes>
      <csr:custom_attribute>
        <csr:type_code>
          <csr:value>data1</csr:value>
        </csr:type_code>
        <csr:group_code>
          <csr:value>wide1</csr:value>
        </csr:group_code>
      </csr:custom_attribute>
      <csr:custom_attribute>
        <csr:type_code>
          <csr:value>data2</csr:value>
        </csr:type_code>
        <csr:group_code>
          <csr:value>wide2</csr:value>
        </csr:group_code>
      </csr:custom_attribute>
   </csr:custom_attributes>

I can only seem to get the first set of data (data1, wide1) but not the second?

   xmlDATA = (From getXMLData In document.<theref:csreai-msg>.<theref:body>.<csr:document>.<csr:service_request>.<csr:custom_attributes>.<csr:custom_attribute>).ToList()

Solution

  • At the top of your code above any class/namespace declarations import the theref namespace:

    Imports <xmlns:theref="http://www.xxxxx.com/Schema/theref">
    

    Then you can just use XML literals to select with

    Option Explicit On
    Option Strict On
    
    Imports <xmlns:theref="http://www.xxxxx.com/Schema/theref">
    
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim xml As String = "<?xml version=""1.0"" encoding=""Windows-1252""?>" & _
                            "<theref:theref-msg xmlns:csr=""http://www.xxxxx.com/Schema/csr"" xmlns:theref=""http://www.xxxxx.com/Schema/theref"">" & _
                              "<theref:header>" & _
                                "<theref:eid />" & _
                                "<theref:reference_id>429</theref:reference_id>" & _
                                "<theref:sr_type_code>US1</theref:sr_type_code>" & _
                                "<theref:event_type_code>REQUEST</theref:event_type_code>" & _
                                "<theref:eai_event_code>DSR</theref:eai_event_code>" & _
                                "<theref:source_code>WORKS</theref:source_code>" & _
                                "<theref:target_code>APP</theref:target_code>" & _
                                "<theref:status_code />" & _
                                "<theref:details />" & _
                              "</theref:header>" & _
                            "</theref:theref-msg>"
    
            Dim document As XDocument = XDocument.Parse(xml)
    
            Dim pupils = From pupil In document.<theref:theref-msg>.<theref:header>
                         Select New With
                                {
                                    .Name = pupil.<theref:reference_id>.Value,
                                    .TagID = pupil.<theref:sr_type_code>.Value
                                }
    
    
            Dim pupilList = pupils.ToList()
    
            For Each pupil In pupilList
                Debug.Print("{0}: {1}", pupil.Name, pupil.TagID)
            Next
        End Sub
    End Class
    

    EDIT

    You need to Import every namespace that you want to use in an XML literal. So your import should now be:

    Imports <xmlns:theref="http://www.xxxxx.com/Schema/theref">
    Imports <xmlns:csr="http://www.xxxxx.com/Schema/csr">
    

    That will clean up the compilation errors. Next you also need to remove <theref:header> from the query since <theref:body> is a sibling to it and not a child. When debugging these kind of things I also recommend always using ToList(). When you got to production you can remove that for performance reasons (I usually don't bother).

    Dim xmlb = (From getXMLData In document.<theref:theref-msg>.<theref:body>.<csr:document>.<csr:header>).ToList()
    

    EDIT 2

    Here's the full code using your new XML data. When I run it I get a messagebox that says "CSR"

    Option Explicit On
    Option Strict On
    
    Imports <xmlns:theref="http://www.xxxxx.com/Schema/theref">
    Imports <xmlns:csr="http://www.xxxxx.com/Schema/csr">
    
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim xml As String = "<?xml version=""1.0"" encoding=""Windows-1252""?>" & _
                         "<theref:theref-msg xmlns:csr=""http://www.xxxxx.com/Schema/csr"" xmlns:theref=""http://www.xxxxx.com/Schema/theref"">" & _
                           "<theref:header>" & _
                             "<theref:eid />" & _
                             "<theref:reference_id>429</theref:reference_id>" & _
                             "<theref:sr_type_code>US1</theref:sr_type_code>" & _
                             "<theref:event_type_code>REQUEST</theref:event_type_code>" & _
                             "<theref:eai_event_code>DSR</theref:eai_event_code>" & _
                             "<theref:source_code>WORKS</theref:source_code>" & _
                             "<theref:target_code>APP</theref:target_code>" & _
                             "<theref:status_code />" & _
                             "<theref:details />" & _
                           "</theref:header>" & _
                           "<theref:body>" & _
                             "<csr:document>" & _
                               "<csr:header>" & _
                                 "<csr:system>CSR</csr:system>" & _
                                 "<csr:doc_name>FULLSR</csr:doc_name>" & _
                                 "<csr:version>3.1</csr:version>" & _
                                 "<csr:dml_event>UPDATE</csr:dml_event>" & _
                               "</csr:header>" & _
                         "</csr:document></theref:body></theref:theref-msg>"
    
            Dim document As XDocument = XDocument.Parse(xml)
    
            Dim xmlb = (From getXMLData In document.<theref:theref-msg>.<theref:body>.<csr:document>.<csr:header>).ToList()
            MsgBox(xmlb.<csr:system>.Value)
    
        End Sub
    End Class
    

    EDIT 3

    Well, you only gave me part of your XML ;) so I had to make some of it up. The trick here is that getXMLData will be an XElement, specifically a <csr:custom_attribute> node. With that you need to go back to your original code and use the Select New... code.

    For convenience I converted your XML string to a raw XDocument because all of the concats was making it hard to read. Remember, my XML might not exactly match yours because you only gave me a portion.

    Option Explicit On
    Option Strict On
    
    Imports <xmlns:theref="http://www.xxxxx.com/Schema/theref">
    Imports <xmlns:csr="http://www.xxxxx.com/Schema/csr">
    
    Public Class Form1
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim document = <?xml version="1.0" encoding="Windows-1252"?>
                           <theref:theref-msg xmlns:csr="http://www.xxxxx.com/Schema/csr" xmlns:theref="http://www.xxxxx.com/Schema/theref">
                               <theref:body>
                                   <csr:document>
                                       <csr:service_request>
                                           <csr:custom_attributes>
                                               <csr:custom_attribute>
                                                   <csr:type_code>
                                                       <csr:value>data1</csr:value>
                                                   </csr:type_code>
                                                   <csr:group_code>
                                                       <csr:value>wide1</csr:value>
                                                   </csr:group_code>
                                               </csr:custom_attribute>
                                               <csr:custom_attribute>
                                                   <csr:type_code>
                                                       <csr:value>data2</csr:value>
                                                   </csr:type_code>
                                                   <csr:group_code>
                                                       <csr:value>wide2</csr:value>
                                                   </csr:group_code>
                                               </csr:custom_attribute>
                                           </csr:custom_attributes>
                                       </csr:service_request>
                                   </csr:document>
                               </theref:body>
                           </theref:theref-msg>
    
            Dim xmlDATA = (
                            From getXMLData In document.<theref:theref-msg>.<theref:body>.<csr:document>.<csr:service_request>.<csr:custom_attributes>.<csr:custom_attribute>
                            Select New With {.TypeCode = getXMLData.<csr:type_code>.<csr:value>.Value, .GroupCode = getXMLData.<csr:group_code>.<csr:value>.Value}
                          ).ToList()
            For Each X In xmlDATA
                Trace.WriteLine(X.TypeCode & ":" & X.GroupCode)
            Next
        End Sub
    End Class