【问题标题】:.net XML deserialization: uppercase and lowercase exception.net XML 反序列化:大写和小写异常
【发布时间】:2015-03-02 12:04:52
【问题描述】:

我在反序列化 .net 中的 XML 时遇到了一些问题。这是我得到的错误:

第 72 行位置 56 上的开始标记“A”与“a”的结束标记不匹配。第 72 行,第 118 位。

如您所见,是同一个标签,但一个是大写的,另一个是小写的。我的 XML 有这样的结构:

<?xml version="1.0"?>
<translationfile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <translationtext>
       <es_text>Spanish text</es_text>
       <en_text>English text</en_text>
       <developer_comment>Plain text</developer_comment>
    </translationtext>
    ....
</translationfile>

这是我的 vb 课

Option Strict Off
Option Explicit On

Imports System.Xml.Serialization

'
'Este código fuente fue generado automáticamente por xsd, Versión=2.0.50727.3038.
'

'''<comentarios/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038"), _
 System.SerializableAttribute(), _
 System.Diagnostics.DebuggerStepThroughAttribute(), _
 System.ComponentModel.DesignerCategoryAttribute("code"), _
 System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True), _
 System.Xml.Serialization.XmlRootAttribute([Namespace]:="", IsNullable:=False)> _
Partial Public Class translationfile

    Private itemsField As List(Of translationfileTranslationtext)

    '''<comentarios/>
    <System.Xml.Serialization.XmlElementAttribute("translationtext", _
        Form:=System.Xml.Schema.XmlSchemaForm.Unqualified)> _
    Public Property Items As List(Of translationfileTranslationtext)
        Get
            Return Me.itemsField
        End Get
        Set(value As List(Of translationfileTranslationtext))
            Me.itemsField = value
        End Set
    End Property
End Class

'''<comentarios/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038"), _
 System.SerializableAttribute(), _
 System.Diagnostics.DebuggerStepThroughAttribute(), _
 System.ComponentModel.DesignerCategoryAttribute("code"), _
 System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class translationfileTranslationtext

    Private es_textField As String

    Private en_textField As String

    Private developer_commentField As String

    '''<comentarios/>
    <System.Xml.Serialization.XmlElementAttribute _
        (Form:=System.Xml.Schema.XmlSchemaForm.Unqualified)> _
    Public Property es_text() As String
        Get
            Return Me.es_textField
        End Get
        Set(value As String)
            Me.es_textField = value
        End Set
    End Property

    '''<comentarios/>
    <System.Xml.Serialization.XmlElementAttribute( _
        Form:=System.Xml.Schema.XmlSchemaForm.Unqualified)> _
    Public Property en_text() As String
        Get
            Return Me.en_textField
        End Get
        Set(value As String)
            Me.en_textField = value
        End Set
    End Property

    '''<comentarios/>
    <System.Xml.Serialization.XmlElementAttribute( _
        Form:=System.Xml.Schema.XmlSchemaForm.Unqualified)> _
    Public Property developer_comment() As String
        Get
            Return Me.developer_commentField
        End Get
        Set(value As String)
            Me.developer_commentField = value
        End Set
    End Property
End Class

问题是两个文本都可能包含 HTML 代码。 XML 由客户端手动生成,我无法更改这些标签内的文本。他们也可以定义自己的标签,如&lt;client27tagname&gt;...&lt;/client27tagname&gt;。例如。这是一个真实的案例:

<translationtext>
    <es_text><p>Nombre</P></es_text>
    <en_text><p>Name</P></en_text>
    <developer_comment>irrelevant text</developer_comment>
</translationtext>

当我尝试反序列化 XML 文件时,我收到了上一个错误,因为 &lt;p&gt; 是小写字母,&lt;/P&gt; 是大写字母。如何在不更改文本的情况下正确反序列化它?是否有可能将这些标签内的所有文本都视为简单字符串?

这是我用于反序列化的代码:

Dim stream As New IO.StreamReader(path)
Dim ser As New Xml.Serialization.XmlSerializer(GetType(translationfile))
Dim myperfil As New translationfile

myperfil = CType(ser.Deserialize(stream), translationfile) 'This line throws the exception
stream.Close()

更新

按照 Olivier 的建议进行更改后。这是我的课:

Option Strict Off
Option Explicit On

Imports System.Xml.Serialization

<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038"), _
 System.SerializableAttribute(), _
 System.Diagnostics.DebuggerStepThroughAttribute(), _
 System.ComponentModel.DesignerCategoryAttribute("code"), _
 System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True), _
 System.Xml.Serialization.XmlRootAttribute([Namespace]:="", IsNullable:=False)> _
Partial Public Class translationfile

    Private itemsField As List(Of translationfileTranslationtext)

    <System.Xml.Serialization.XmlElementAttribute("translationtext", Form:=System.Xml.Schema.XmlSchemaForm.Unqualified)> _
    Public Property Items As List(Of translationfileTranslationtext)
        Get
            Return Me.itemsField
        End Get
        Set(value As List(Of translationfileTranslationtext))
            Me.itemsField = value
        End Set
    End Property
End Class

<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038"), _
 System.SerializableAttribute(), _
 System.Diagnostics.DebuggerStepThroughAttribute(), _
 System.ComponentModel.DesignerCategoryAttribute("code"), _
 System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class translationfileTranslationtext

    Private es_textField As String

    Private en_textField As String

    Private developer_commentField As String

    <XmlIgnore()>
    Public Property es_text() As String
        Get
            Return Me.es_textField
        End Get
        Set(value As String)
            Me.es_textField = value
        End Set
    End Property

    <XmlElement(ElementName:="es_text", Form:=System.Xml.Schema.XmlSchemaForm.Unqualified)> _
    Public Property es_HtmlText() As String
        Get
            Return System.Web.HttpUtility.HtmlEncode(Me.es_textField)
        End Get
        Set(value As String)
            Me.es_textField = HttpUtility.HtmlDecode(value)
        End Set
    End Property

    <XmlIgnore()>
    Public Property en_text() As String
        Get
            Return Me.en_textField
        End Get
        Set(value As String)
            Me.en_textField = value
        End Set
    End Property

    <XmlElement(ElementName:="en_text", Form:=System.Xml.Schema.XmlSchemaForm.Unqualified)> _
    Public Property en_HtmlText() As String
        Get
            Return System.Web.HttpUtility.HtmlEncode(Me.en_textField)
        End Get
        Set(value As String)
            Me.en_textField = HttpUtility.HtmlDecode(value)
        End Set
    End Property
       <System.Xml.Serialization.XmlElementAttribute(Form:=System.Xml.Schema.XmlSchemaForm.Unqualified)> _
    Public Property developer_comment() As String
        Get
            Return Me.developer_commentField
        End Get
        Set(value As String)
            Me.developer_commentField = value
        End Set
    End Property
End Class

【问题讨论】:

  • 在 XML 文件中反序列化之前将所有:"" 替换为 "" :)
  • 另外,检查XML文件的生成,不控制标签的格式是一个巨大的错误,因为XML标签在大多数情况下都是区分大小写的。
  • 这不是 XML,因此 XML 反序列化不起作用。您必须手动解析文件,例如使用 XDocument,并使用节点 &lt;en_text&gt;InnerText,它位于 Value 属性中。
  • XML 区分大小写(在标准中)。这意味着您的 cade 可以忽略案例,但任何其他 Xml 解析器都不能。这意味着只有您可以正常使用此 Xml 文档。三思而后行!我认为最好的方法是在反序列化之前检查 xml,即使在创建 XML 时为什么有些标签有大写 ..! ?

标签: .net xml vb.net serialization


【解决方案1】:

使用HttpUtility.HtmlEncode 对文本进行编码,使用HttpUtility.HtmlDecode 对其进行解码。

您可以为此创建一个附加属性,并从序列化中排除原始属性。

'Exclude the original property from serialization
<XmlIgnore()> _
Public Property en_text() As String
    Get
        Return Me.en_textField
    End Get
    Set(value As String)
        Me.en_textField = value
    End Set
End Property

'Name the encoding/decoding property element like the original property
<XmlElement(ElementName := "en_text", Form:=XmlSchemaForm.Unqualified)> _
Public Property en_HtmlEncodedText() As String
    Get
        Return HttpUtility.HtmlEncode(Me.en_textField)
    End Get
    Set(value As String)
        Me.en_textField = HttpUtility.HtmlDecode(value)
    End Set
End Property

Html 编码会将"&lt;""&gt;" 转换为"&amp;lt;""&amp;gt;",从而使内部标签对XML 不可见。


更新

Mt 解决方案有效。我现在已经测试过了。您可能已经使用仍然包含纯文本 ("&lt;p&gt;Name&lt;/P&gt;") 的 html 标记的 XML 对其进行了测试。我的代码所做的是将 html 写为"&amp;amp;lt;p&amp;amp;gt;Name&amp;amp;lt;/P&amp;amp;gt;"。这就是HttpUtility.HtmlEncode 所做的。因此,您必须首先使用我的方法编写一个 XML 文件。只有这样,阅读才会成功。

这是我的写作测试:

Public Sub WriteTest()
    Dim myperfil As New translationfile With {
        .Items = New List(Of translationfileTranslationtext) From {
            New translationfileTranslationtext With {.en_text = "en test", .es_text = "spanish"},
            New translationfileTranslationtext With {.en_text = "<p>Name</P>", .es_text = "<p>Nombre</P>"}
        }
    }

    Dim writer As New IO.StreamWriter(path)
    Dim ser As New XmlSerializer(GetType(translationfile))
    ser.Serialize(writer, myperfil)
    writer.Close()
End Sub

它创建以下 XML:

?xml version="1.0" encoding="utf-8"?>
<translationfile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <translationtext>
    <es_text>spanish</es_text>
    <en_text>en test</en_text>
  </translationtext>
  <translationtext>
    <es_text>&amp;lt;p&amp;gt;Nombre&amp;lt;/P&amp;gt;</es_text>
    <en_text>&amp;lt;p&amp;gt;Name&amp;lt;/P&amp;gt;</en_text>
  </translationtext>
</translationfile>

这是我的阅读测试,它抛出 no 异常:

Public Sub ReadTest()
    Dim myperfil As translationfile
    Dim reader As New IO.StreamReader(path)
    Dim ser As New XmlSerializer(GetType(translationfile))

    myperfil = CType(ser.Deserialize(reader), translationfile)
    reader.Close()

    For Each item As translationfileTranslationtext In myperfil.Items
        Console.WriteLine("EN = {0}, ES = {1}", item.en_text, item.es_text)
    Next
    Console.ReadKey()
End Sub

它将这个写入控制台:

EN = en test, ES = spanish
EN = <p>Name</P>, ES = <p>Nombre</P>

【讨论】:

  • 感谢您的回答。但是,我为两个属性 es_text 和 en_text 复制粘贴了您的代码。同样的结果:(我想我必须手动解析它。
  • 在此更改之后您的序列化文本(XML)包含什么?
  • 我已经更新了我之前的问题,向您展示我是如何改变我的班级的。正如我所说,我在同一行上遇到了同样的异常。
【解决方案2】:

经过一些测试,我找到了解决方法。

  1. 我将所有文本作为一个简单的字符串获取
  2. 我将所有 &lt; 字符替换为默认字符串:#open_key#
  3. 我将所有#open_key#es_text&gt; 替换为&lt;es_text&gt;
  4. en_text、developer_coment 等也一样...
  5. 我将结果保存到一个临时文件中
  6. 我反序列化临时文件
  7. 在做出响应之前,我将所有#open_key#替换为&lt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-24
    • 2016-04-06
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多