0

I have a huge XML file being returned from a web service call and am working on parsing it. One issue I'm having is parsing multiple elements (with the same name) into a List(Of String). The XML looks like so

<BasicPropertyInfo ChainCode="CY" GEOConfidenceLevel="3" HotelCityCode="KWI" HotelCode="0048191" HotelName="COURTYARD KUWAIT CITY MARRIOTT" Latitude="29.377052" Longitude="47.990384" NumFloors="21" RPH="001">
  <Address>
    <AddressLine>AL SHUHADA ST PO BOX 1216 DASM</AddressLine>
    <AddressLine>DASMAN KUWAIT CITY KW 15463</AddressLine>
    <CountryCode>KW</CountryCode>
  </Address>
  <Award Provider="NTM3 CROWN" />
  <ContactNumbers>
    <ContactNumber Phone="965-22997000" Fax="965-22997001" />
  </ContactNumbers>

And my class is simple enough

Namespace Classes.Models
    Public Class PropertyInfo
        Public Property ChainCode() As String
        Public Property HotelCityCode() As String
        Public Property HotelCode() As String
        Public Property HotelName() As String
        Public Property Address() As IEnumerable(Of String)
        Public Property PhoneNumber() As String
        Public Property FaxNumber() As String
    End Class
End Namespace

In the following code if I remove where I'm trying to get AddressLine it populates the class, as soon as I add the code it bombs with the error of

Unable to cast object of type 'd__142[System.Xml.Linq.XElement,System.Char]' to type 'System.Collections.Generic.IEnumerable1[System.String]'.

Public Function ParsePropertyInfo() As IEnumerable(Of PropertyInfo)
    Try
        Dim ns As XNamespace = "http://webservices.sabre.com/sabreXML/2003/07"
        Dim prop As PropertyInfo

        For Each n As XElement In _xDoc.Descendants(ns + "BasicPropertyInfo")
            _properties.Add(New PropertyInfo With { _
                             .ChainCode = n.Attribute("ChainCode").Value, _
                             .HotelCityCode = n.Attribute("HotelCityCode").Value, _
                             .HotelCode = n.Attribute("HotelCode").Value, _
                             .HotelName = n.Attribute("HotelName").Value,
                             .PhoneNumber = n.Element(ns + "ContactNumbers").Element(ns + "ContactNumber").Attribute("Phone").Value, _
                              .Address = n.Descendants(ns + "AddressLine").SelectMany(Function(el As String) el), _
                             .FaxNumber = n.Element(ns + "ContactNumbers").Element(ns + "ContactNumber").Attribute("Fax").Value})


        Next

        Return _properties
    Catch ex As Exception
        ErrorMessage = ex.Message
        Return Nothing
    End Try
End Function

So how would I go about getting the AddressLine elements into my generic list?

1 Answer 1

2

Use Select instead of SelectMany:

.Address = n.Descendants(ns + "AddressLine").Select(Function(el As String) el)

SelectMany looks at your IEnumerable(Of XElement), transforms each XElement to string, and then merges all characters from these string to one, huge collection of char. That's because string implements IEnumerable(Of char).

And you should probably add ToList() call after Select, to make sure you just store a collection of string instances, not a query definition, which will be executed every time you access the property.

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

Comments

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.