【问题标题】:How to preserve any new xml keys when deserializing an XML string to a class, modify some values then reserialize将 XML 字符串反序列化为类时如何保留任何新的 xml 键,修改一些值然后重新序列化
【发布时间】:2020-05-22 20:28:54
【问题描述】:

这是我的问题的示例代码。

<System.Xml.Serialization.XmlType(TypeName:="Person")>
Public Class clsXMLtest
    Public FirstName As String
    Public LastName As String
End Class

Dim x As clsXMLtest
Dim s1 As String = "<Person>
                      <FirstName>Jack</FirstName>
                      <LastName>Hill</LastName>
                   </Person>"
Dim xmlSer As New System.Xml.Serialization.XmlSerializer(GetType(clsXMLtest))
x = CType(xmlSer.Deserialize(New IO.StringReader(s1)), clsXMLtest)
x.LastName = "Pike"
Dim sw As New IO.StringWriter
xmlSer.Serialize(sw, x)
Dim s2 As String = sw.ToString


Dim s3 As String = "<Person>
                      <FirstName>Jack</FirstName>
                      <LastName>Hill</LastName>
                      <NewKey>NEW</NewKey>
                   </Person>"
x = CType(xmlSer.Deserialize(New IO.StringReader(s3)), clsXMLtest)
x.LastName = "Jack"
sw = New IO.StringWriter
xmlSer.Serialize(sw, x)
Dim s4 As String = sw.ToString

最终输出不再包含新密钥 NewKey
如何保留添加到原始 XML 中的任何新键?

【问题讨论】:

  • clsXMLTest 中不存在该属性(我猜,请提供定义),因此您无法对其进行序列化。 How to preserve any new keys added to the original XML? 这不是它的工作原理。通过像 New XmlSerializer(GetType(clsXMLtest)) 这样声明序列化程序,它只知道该类中的属性。
  • 这就是重点,XML 键 稍后会被添加到 XML 字符串中,(由其他进程)。但是,每当“旧”代码访问此 XML 时,新设置就会丢失。
  • 所以将属性添加到类定义中。这个xmlSer.Serialize(sw, x) 仍在使用New XmlSerializer(GetType(clsXMLtest)),所以它只知道如何序列化clsXMLtest 中描述的属性。 x 第二次反序列化后看什么?你能看到那个属性吗?当然不是因为 1. 它没有定义,2. 它不知道将 &lt;NewKey&gt;NEW&lt;/NewKey&gt; 分配给什么类型没有定义。
  • 你有一个圆钉、方钉和圆孔。圆钉穿过圆孔,方钉被丢弃。
  • 为了实现这一点,而不是向 xml 添加全新的元素,您应该拥有某种元素集合,其中包含名称/值对。然后,您可以添加任意数量的内容,序列化会将它们接受到列表中。

标签: .net xml vb.net


【解决方案1】:

我会将类更改为此,添加一个新属性,即List(Of NewElement)

<XmlRoot("Person")>
Public Class clsXMLtest
    <XmlElement>
    Public Property FirstName As String
    <XmlElement>
    Public Property LastName As String
    <XmlElement("NewElement")>
    Public Property NewElements As List(Of NewElement)
End Class

Public Class NewElement
    <XmlAttribute>
    Public Property Name As String
    <XmlAttribute>
    Public Property Value As String
End Class

反序列化

Dim s3 As String = "<Person>
                        <FirstName>Jack</FirstName>
                        <LastName>Hill</LastName>
                        <NewElement Name=""NewKey"" Value=""NEW""/>
                        <NewElement Name=""OtherKey"" Value=""OTHER""/>
                    </Person>"
x = CType(xmlSer.Deserialize(New IO.StringReader(s3)), clsXMLtest)

【讨论】:

  • 您对 s3 的看法是正确的。我了解您关于创建 ListOf 的想法,它会起作用。缺点是,代码将无法更新为具有新设置的强类型。即 Public NewKey 作为字符串
  • 嘿嘿固定,谢谢
  • 对,当然。但是您已经开始在类中为新属性定义 no 了,所以这至少是一个小的改进。你可以稍后再投,即Dim i As Integer = Integer.Parse(x.NewElements.Where(Function(e) e.Name = "ID").Single())
【解决方案2】:

使用XmlAnyElementAttribute:

class Person
{
    ...

    // Apply the XmlAnyElementAttribute to a field
    // returning an array of XmlElement objects.
    // XmlSerializer will put all unknown elements here
    // on deserialization, and serialize them back.
    [XmlAnyElement]
    public XmlElement[] AllElements ;
}

【讨论】:

  • 太棒了 就是这样。
猜你喜欢
  • 2021-11-28
  • 2023-01-12
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 2016-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多