将xml反序列化为object

时间:2013-07-23 17:43:34

标签: xml vb.net

我有两个相同的XML文件,其中包含有关人员的信息。他们的标签名称不同。例如对于第一个,我有

<name>
<surname>
<address>... 

在第二个,我有

<name_person>
<surname_person>
<address_person>

我需要在vb.net中将它们“反序列化”为两个单独的对象。 我只有一个类具有属性名称,姓氏,地址.. 是否可以仅将这一个类用于第二个XML文件?因为后者的标记名称不匹配。

感谢

3 个答案:

答案 0 :(得分:1)

最简单的事情,我认为是分别控制反序列化。我找了寻找XmlElement属性的别名,但我没有看到类似的东西。此外,当您再次序列化对象时,它将如何知道它应该使用哪些标记。

从第二个对象反序列化后,在代码中创建第一个类的新实例并复制属性并不困难。

你也可以这样做,这使得一个类非常适合阅读,但你不应该使用这个类进行写作,否则它会写出所有的属性。

VB.NET

<XmlRoot("PersonList")> _
Public Class PersonList
    <XmlElement("person")> _
    Public Property People() As Person()
        Get
            Return m_People
        End Get
        Set
            m_People = Value
        End Set
    End Property
    Private m_People As Person()
End Class

Public Class Person
    Private _name As String

    <XmlElement("name")> _
    Public Property Name() As String
        Get
            Return _name
        End Get
        Set
            _name = value
        End Set
    End Property

    <XmlElement("name_person")> _
    Public Property NamePerson() As String
        Get
            Return _name
        End Get
        Set
            _name = value
        End Set
    End Property

End Class

C#

[XmlRoot("PersonList")]
public class PersonList {
    [XmlElement("person")]
    public Person[] People { get; set; }
}

public class Person {
    private String _name;

    [XmlElement("name")]
    public String Name {get{return _name;} set{_name = value;}}

    [XmlElement("name_person")]
    public String NamePerson {get{return _name;} set{_name = value;}}

}

参考:XML deserialize: different xml schema maps to the same C# class

或者,看起来您可以使用原始类,但随后处理XmlSerializer.UnknownElement事件。

(未测试的) VB.Net

Private Shared Sub serializer_UnknownElement(sender As Object, e As XmlElementEventArgs)
    Dim target = DirectCast(e.ObjectBeingDeserialized, Person)
    If e.Element.Name = "name_person" Then
        target.Name = e.Element.InnerText
    End If
End Sub

C#

static void serializer_UnknownElement(object sender, XmlElementEventArgs e)
{
    var target = (Person) e.ObjectBeingDeserialized;
    if( e.Element.Name == "name_person")
    {
        target.Name = e.Element.InnerText;
    }
}

但同样,这不会让你保存回旧格式,只能从旧格式加载到新类中。

参考:http://weblogs.asp.net/psteele/archive/2011/01/31/xml-serialization-and-the-obsolete-attribute.aspx

参考:http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.unknownelement.aspx

答案 1 :(得分:0)

您应该可以使用SerializationBinder来指定(重新映射)要反序列化的元素的类型。

答案 2 :(得分:0)

您可以使用XSLT更新第二个文档以匹配您期望的元素名称。这样,您就不必处理代码中的不同元素名称。

使用XSLT转换第二个文档,如:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="//name_person">
    <name>
     <xsl:apply-templates select="@*|node()" />
    </name>
  </xsl:template>
  <xsl:template match="//surname_person">
    <surname>
      <xsl:apply-templates select="@*|node()" />
    </surname>
  </xsl:template>
  <xsl:template match="//address_person">
    <address>
      <xsl:apply-templates select="@*|node()" />
    </address>
  </xsl:template>
</xsl:stylesheet>

它以编程方式将此应用于您的文档,在C#中,您可以这样做:

XslCompiledTransformtransform = new XslCompiledTransform(); 
transorm.Load("update.xsl"); 
transorm.Transform("source.xml","new.xml"); 

在VB中:

Dim transform As XslTransform
transform = New XslTransform()
transform .Load("update.xsl")
transform .Transform("source.xml", "new.xml")

结果将是两个文档中的元素名称匹配,然后您可以在XML上运行反序列化器,而不必担心处理不匹配的元素名称。