简体   繁体   中英

vb.NET and complex XML structure

I am attempting to turn an xml file into a complex object class, I'm not sure why the Visual Studio/Edit/Past Special as XML Class doesn't work right. When I run this code I get the "Additional information: There is an error in XML document (24, 4) error."

Dim serializer As New XmlSerializer(GetType(rates))
Dim reader As New StreamReader("d:\1Q2017.xml")
Dim rts As New rates
rts = serializer.Deserialize(reader)
reader.Close()

My Class:

Public Class rates

'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True),
 System.Xml.Serialization.XmlRootAttribute([Namespace]:="", IsNullable:=False)>
Partial Public Class FILE

    Private tITLEField As String

    Private qUARTERField As String

    Private lINKField As String

    Private eXCHANGE_RATEField As String

    Private rECORDField() As FILERECORD

    Private fOOTNOTESField() As FILEFOOTNOTE

    '''<remarks/>
    Public Property TITLE() As String
        Get
            Return Me.tITLEField
        End Get
        Set
            Me.tITLEField = Value
        End Set
    End Property

    '''<remarks/>
    Public Property QUARTER() As String
        Get
            Return Me.qUARTERField
        End Get
        Set
            Me.qUARTERField = Value
        End Set
    End Property

    '''<remarks/>
    Public Property LINK() As String
        Get
            Return Me.lINKField
        End Get
        Set
            Me.lINKField = Value
        End Set
    End Property

    '''<remarks/>
    Public Property EXCHANGE_RATE() As String
        Get
            Return Me.eXCHANGE_RATEField
        End Get
        Set
            Me.eXCHANGE_RATEField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlElementAttribute("RECORD")>
    Public Property RECORD() As FILERECORD()
        Get
            Return Me.rECORDField
        End Get
        Set
            Me.rECORDField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlArrayItemAttribute("FOOTNOTE", IsNullable:=False)>
    Public Property FOOTNOTES() As FILEFOOTNOTE()
        Get
            Return Me.fOOTNOTESField
        End Get
        Set
            Me.fOOTNOTESField = Value
        End Set
    End Property
End Class

'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)>
Partial Public Class FILERECORD

    Private itemsField() As Object

    Private itemsElementNameField() As ItemsChoiceType

    '''<remarks/>
    <System.Xml.Serialization.XmlElementAttribute("COUNTRY", GetType(String)),
     System.Xml.Serialization.XmlElementAttribute("FUEL_TYPE", GetType(String)),
     System.Xml.Serialization.XmlElementAttribute("JURISDICTION", GetType(FILERECORDJURISDICTION)),
     System.Xml.Serialization.XmlElementAttribute("RATE", GetType(FILERECORDRATE)),
     System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")>
    Public Property Items() As Object()
        Get
            Return Me.itemsField
        End Get
        Set
            Me.itemsField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlElementAttribute("ItemsElementName"),
     System.Xml.Serialization.XmlIgnoreAttribute()>
    Public Property ItemsElementName() As ItemsChoiceType()
        Get
            Return Me.itemsElementNameField
        End Get
        Set
            Me.itemsElementNameField = Value
        End Set
    End Property
End Class

'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)>
Partial Public Class FILERECORDJURISDICTION

    Private idField As String

    Private sURCHARGEField As String

    Private valueField As String

    '''<remarks/>
    <System.Xml.Serialization.XmlAttributeAttribute()>
    Public Property ID() As String
        Get
            Return Me.idField
        End Get
        Set
            Me.idField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlAttributeAttribute()>
    Public Property SURCHARGE() As String
        Get
            Return Me.sURCHARGEField
        End Get
        Set
            Me.sURCHARGEField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlTextAttribute()>
    Public Property Value() As String
        Get
            Return Me.valueField
        End Get
        Set
            Me.valueField = Value
        End Set
    End Property
End Class

'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)>
Partial Public Class FILERECORDRATE

    Private cOUNTRYField As String

    Private rATECHANGEField As Byte

    Private valueField As Decimal

    '''<remarks/>
    <System.Xml.Serialization.XmlAttributeAttribute()>
    Public Property COUNTRY() As String
        Get
            Return Me.cOUNTRYField
        End Get
        Set
            Me.cOUNTRYField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlAttributeAttribute()>
    Public Property RATECHANGE() As Byte
        Get
            Return Me.rATECHANGEField
        End Get
        Set
            Me.rATECHANGEField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlTextAttribute()>
    Public Property Value() As Decimal
        Get
            Return Me.valueField
        End Get
        Set
            Me.valueField = Value
        End Set
    End Property
End Class

'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(IncludeInSchema:=False)>
Public Enum ItemsChoiceType

    '''<remarks/>
    COUNTRY

    '''<remarks/>
    FUEL_TYPE

    '''<remarks/>
    JURISDICTION

    '''<remarks/>
    RATE
End Enum

'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)>
Partial Public Class FILEFOOTNOTE

    Private idField As String

    Private jURISDICTIONField As String

    Private valueField As String

    '''<remarks/>
    <System.Xml.Serialization.XmlAttributeAttribute()>
    Public Property ID() As String
        Get
            Return Me.idField
        End Get
        Set
            Me.idField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlAttributeAttribute()>
    Public Property JURISDICTION() As String
        Get
            Return Me.jURISDICTIONField
        End Get
        Set
            Me.jURISDICTIONField = Value
        End Set
    End Property

    '''<remarks/>
    <System.Xml.Serialization.XmlTextAttribute()>
    Public Property Value() As String
        Get
            Return Me.valueField
        End Get
        Set
            Me.valueField = Value
        End Set
    End Property
End Class

End Class

and here is the XML file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE FILE [
<!ELEMENT FILE (TITLE, QUARTER, LINK, EXCHANGE_RATE, RECORD+, FOOTNOTES+)>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT QUARTER (#PCDATA)>
<!ELEMENT LINK (#PCDATA)>
<!ELEMENT EXCHANGE_RATE (#PCDATA)>

<!ELEMENT RECORD (JURISDICTION, COUNTRY, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+, FUEL_TYPE, RATE+)>
<!ELEMENT JURISDICTION (#PCDATA)>
<!ATTLIST JURISDICTION ID CDATA #IMPLIED> 
<!ATTLIST JURISDICTION EFFECTIVE_DATE CDATA #IMPLIED> 
<!ATTLIST JURISDICTION SURCHARGE CDATA #IMPLIED> 
<!ELEMENT COUNTRY (#PCDATA)>
<!ELEMENT FUEL_TYPE (#PCDATA)>  
<!ELEMENT RATE (#PCDATA)>
<!ATTLIST RATE COUNTRY (US|CAN) #REQUIRED>  
<!ATTLIST RATE RATECHANGE (1|0) #REQUIRED>  

<!ELEMENT FOOTNOTES (FOOTNOTE+)>
<!ELEMENT FOOTNOTE (#PCDATA)> 
<!ATTLIST FOOTNOTE ID CDATA #IMPLIED>  
<!ATTLIST FOOTNOTE JURISDICTION CDATA #IMPLIED>  
]>
<FILE>
  <TITLE> Final Fuel Tax Rates </TITLE>
  <QUARTER>1Q2017</QUARTER>
  <LINK>http://www.iftach.org/TaxMatrix/charts/1Q2017.xml</LINK>
  <EXCHANGE_RATE>U.S./Canada Exchange Rate 1.3395 - 0.7465</EXCHANGE_RATE>
  <RECORD>
    <JURISDICTION ID="#15"  >AB</JURISDICTION>
    <COUNTRY>CAN</COUNTRY>
    <FUEL_TYPE>Gasoline</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">0.4942</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.1749</RATE>
      <FUEL_TYPE>Special Diesel</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">0.5185</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.1835</RATE>
      <FUEL_TYPE>Gasohol</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="0">0.3674</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
      <FUEL_TYPE>Propane</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">0.3527</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.1248</RATE>
      <FUEL_TYPE>LNG</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">0.1068</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.0378</RATE>
      <FUEL_TYPE>CNG</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">1.0681</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.3780</RATE>
      <FUEL_TYPE>Ethanol</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="0">0.3674</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
      <FUEL_TYPE>Methanol</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">0.4290</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.1518</RATE>
      <FUEL_TYPE>E-85</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">0.3863</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.1367</RATE>
      <FUEL_TYPE>M-85</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">0.4388</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.1553</RATE>
      <FUEL_TYPE>A55</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="1">0.4244</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="1">0.1502</RATE>
      <FUEL_TYPE>Biodiesel</FUEL_TYPE>
      <RATE COUNTRY="US" RATECHANGE="0">0.3674</RATE>
      <RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
  </RECORD>
</FILE>

I apologize if this has already been covered, but I search high and low and could not find an example of how to handle these, the XML formats correctly when trying the online formatters.

The XML you are receiving is not valid.

The FILE element is declared as follows:

<!ELEMENT FILE (TITLE, QUARTER, LINK, EXCHANGE_RATE, RECORD+, FOOTNOTES+)>

But the FILE tag in the actual XML doesn't have a FOOTNOTES child element.

Your classes seem fine. Instead of nesting them in a new class, rates , just deserialize to the FILE class.

Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(FILE))
Dim f As FILE
Using reader As New System.IO.StreamReader("XMLFile1.xml")
    f = serializer.Deserialize(reader)
End Using

EDIT

In my testing environment

  • Tested with .NET frameworks 2, 3, 3.5, 4, 4.5, and 4.6.2. It works
  • Added fully qualified class names (namespaces before some .NET class names so you don't need to import them).
  • To test, I added a new xml file to my project, then copied the entire XML to the file, and right clicked on the file >> properties >> set Copy to Output Directory = Copy Always . I did this because I don't have "d:\\1Q2017.xml"
  • I also made sure that the FILE class is marked Public . If it's defined in Module1 , then declare Public Module Module1 , or move outside of Module1 and just make it Public

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM