Неожиданная ошибка элемента типа узла при десериализации - PullRequest
1 голос
/ 19 марта 2020

Я пытаюсь разобрать большой словарь с английского на английский sh, написанный на XML. Типичная запись выглядит так:

<entry>
<ent_seq>1486440</ent_seq>
<k_ele>
<keb>美術</keb>
<ke_pri>ichi1</ke_pri>
<ke_pri>news1</ke_pri>
<ke_pri>nf02</ke_pri>
</k_ele>
<r_ele>
<reb>びじゅつ</reb>
<re_pri>ichi1</re_pri>
<re_pri>news1</re_pri>
<re_pri>nf02</re_pri>
</r_ele>
<sense>
<pos>&n;</pos>
<pos>&adj-no;</pos>
<gloss>art</gloss>
<gloss>fine arts</gloss>
</sense>
<sense>
<gloss xml:lang="dut">kunst</gloss>
<gloss xml:lang="dut">schone kunsten</gloss>
</sense>
<sense>
<gloss xml:lang="fre">art</gloss>
<gloss xml:lang="fre">beaux-arts</gloss>
</sense>
<sense>
<gloss xml:lang="ger">Kunst</gloss>
<gloss xml:lang="ger">die schönen Künste</gloss>
<gloss xml:lang="ger">bildende Kunst</gloss>
</sense>
<sense>
<gloss xml:lang="ger">Produktionsdesign</gloss>
<gloss xml:lang="ger">Szenographie</gloss>
</sense>
<sense>
<gloss xml:lang="hun">művészet</gloss>
<gloss xml:lang="hun">művészeti</gloss>
<gloss xml:lang="hun">művészi</gloss>
<gloss xml:lang="hun">rajzóra</gloss>
<gloss xml:lang="hun">szépművészet</gloss>
</sense>
<sense>
<gloss xml:lang="rus">изящные искусства; искусство</gloss>
<gloss xml:lang="rus">{~{的}} художественный, артистический</gloss>
</sense>
<sense>
<gloss xml:lang="slv">umetnost</gloss>
<gloss xml:lang="slv">likovna umetnost</gloss>
</sense>
<sense>
<gloss xml:lang="spa">bellas artes</gloss>
</sense>
</entry>

Я написал десериализатор на основе кода, предоставленного djv в этом ответе , и он действительно десериализует весь словарь в серию Объекты класса. Вот код, который я получил до сих пор:

ReadOnly jmdictpath As String = "JMdict"

<XmlRoot>
Public Class JMdict
    <XmlElement("entry")>
    Public Property entrylist As List(Of entry)
End Class

<Serializable()>
Public Class entry
    Public Property ent_seq As Integer
    Public Property k_ele As k_ele
    Public Property r_ele As r_ele
    <XmlElement("sense")>
    Public Property senselist As List(Of sense)
End Class

<Serializable()>
Public Class k_ele
    Public Property keb As String
    Public Property ke_pri As List(Of String)
    Public Property ke_inf As List(Of String)
End Class

<Serializable()>
Public Class r_ele
    Public Property reb As String
    Public Property re_pri As List(Of String)
    Public Property ke_inf As List(Of String)
End Class

<Serializable()>
Public Class sense
    <XmlElement("pos")>
    Public Property pos As List(Of string)
    <XmlElement("gloss")>
    Public Property gloss As List(Of gloss)
End Class

<Serializable()>
Public Class gloss
    <XmlAttribute("xml:lang")>
    Public Property lang As String
    <XmlAttribute("g_type")>
    Public Property g_type As String
    <XmlText>
    Public Property Text As String
    Public Overrides Function ToString() As String
        Return Text
    End Function
End Class

Dim dict As JMdict

Sub Deserialise()
    Dim serialiser As New XmlSerializer(GetType(JMdict))
    Using sr As New StreamReader(jmdictpath)
        dict = CType(serialiser.Deserialize(sr), JMdict)
    End Using
End Sub

Однако, когда я запускаю код, я получаю следующую ошибку:

System.InvalidOperationException: 'Существует ошибка в документе XML (415, 7). '

XmlException: непредвиденный тип узла EntityReference. Метод ReadElementString можно вызывать только для элементов с простым или пустым содержимым. Строка 415, позиция 7.

Я проверил XML, а строка 415 - это строка:

 <pos>&unc;</pos>

Таким образом, десериализатор испытывает проблемы с чтением <pos> тег. Поэтому я попробовал несколько вещей.

Сначала я попытался удалить тег <XMLElement> для pos в классе sense. Это означало, что ошибки не было, но десериализатор просто не считывал данные для pos ни для одной из записей.

Во-вторых, я проверил StackOverflow и обнаружил, что это связано Вопрос, где у ОП была такая же проблема . Принятый ответ на этот вопрос предложил разбить данные на следующие классы , поэтому я тоже попробовал это и создал новый класс pos:

<Serializable()>
Public Class sense
    <XmlElement("pos")>
    Public Property pos As List(Of pos)
    <XmlElement("gloss")>
    Public Property gloss As List(Of gloss)
End Class

<Serializable()>
Public Class pos
    <XmlText>
    Public Property Text As String
    Public Overrides Function ToString() As String
        Return Text
    End Function
End Class

И еще раз, пока этот не вызвал ошибок, элемент pos был пустым в каждой записи. Каждый тег pos содержит только одно значение - хотя может быть более одного тега pos на тег sense - поэтому я не думал, что ему нужен собственный объект класса. В любом случае, этот ответ не решил мою проблему, поэтому я и задаю этот вопрос.

Я совершенно новичок в десериализации XML и не совсем понимаю, что я делаю в Глубина - я пытаюсь понять механику этого на основе этот полезный ответ , но я, очевидно, здесь что-то не так. Любой совет будет оценен.

1 Ответ

1 голос
/ 20 марта 2020

Вам просто нужно создать XmlSerializer с XmlReader с правильно настроенным XmlReaderSettings . Единственное, что вам нужно настроить в настройках - это свойство DtdProcessing , равное DtdProcessing.Parse.

Dim settings As XmlReaderSettings = New XmlReaderSettings()
settings.DtdProcessing = DtdProcessing.Parse

Dim xmlPath As String = Path.Combine(Application.StartupPath, "yourfilename.xml")

Dim ser As New XmlSerializer(GetType(JMdict))

Dim JMdictInstance As JMdict
Using rdr As XmlReader = XmlReader.Create(xmlPath, settings)
   JMdictInstance = CType(ser.Deserialize(rdr), JMdict)
End Using
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...