首页 > 解决方案 > XML 序列化具有 xml-element 的 xml-attribute

问题描述

我必须为在其他软件中的导入创建 XML 文档。导入过程不能修改,所以xml和他的结构是固定的。

我在visualstudio 中使用VB.net。我使用“Xml.Serialization.XmlSerializer”,过去对我来说很好用。

对于这个主题,我通常将整个 xml 结构“重建”为具有“xml 修饰符”的类,如下所示:

Public Class Xyz
    <xmlattribute> property id as integer
    <xmlelement> property name as string
    <xmlelement> property comment as string
    <xmlelement> property block as string
    <xmlelement> property test as List(of Test)

    Public Sub New()
        test = new List(of Test)
    End Sub
End Class

Public Class Test
    <xmlelement> property name as string
End Class

然后我得到这样的xml部分:

<Xyz id=0>
 <Name>Abc</Name>
 <Comment>Abc</Comment>
 <Block>Abc</Block>
 <Test>
  <Name>Abc</Name>
 </Test>
 <Test>
  <Name>Def</Name>
 </Test>
 <Test>
  <Name>Ghi</Name>
 </Test>
</Xyz>

但是现在我在 xml 中有两个问题,我需要任何人的启发。首先,“块”有一个直接值(像以前一样)和一个像“id_block”这样的属性。其次,“测试”元素有一个序列号。导入必须如下所示:

<Xyz id=0>
 <Name>Abc</Name>
 <Comment>Abc</Comment>
 <Block id_Block=5>Abc</Block>
 <Test_0>
  <Name>Abc</Name>
 </Test_0>
 <Test_1>
  <Name>Def</Name>
 </Test_1>
 <Test_2>
  <Name>Ghi</Name>
 </Test_2>
</Xyz>

我怎样才能实现这两个主题?

标签: xmlvb.netserializationxml-serializationxmlserializer

解决方案


您在下面看到的我的解决方案。它对我有用,但是...

我不明白的是,为什么我需要在父类和(索引)子类中使用 IXMLSERIALIZER。我进行了其他测试,但它不起作用。每次都是例如内部的“test”标签,而不仅仅是“test_1”标签。对此或其他/更好的解决方案有什么好的解释吗?

我的代码:

  Public Class Xyz
        Inherits IndexedParent

        <XmlAttribute> Property id As Integer
        <XmlElement> Property name As String
        <XmlElement> Property comment As String
        <XmlElement> Property block As String
        <XmlIgnore> Property test As List(Of Test)
        <XmlIgnore> Property tryNext As List(Of TryNext)


        Public Sub New()
            test = New List(Of Test)
            tryNext = New List(Of TryNext)
            RegisterIndexedChildList(test)
            RegisterIndexedChildList(tryNext)
        End Sub

    End Class

    Public Class Test
        Inherits IndexedChild

        <XmlElement> Property Name As String
        <XmlElement> Property Name2 As String


    End Class


    Public Class TryNext
        Inherits IndexedChild

        <XmlElement> Property N As String
        <XmlElement> Property N2 As String

    End Class

    Public MustInherit Class IndexedParent
        Implements IXmlSerializable

        Private registeredChildLists As List(Of IEnumerable(Of IndexedChild))

        Public Sub RegisterIndexedChildList(pChildList As IEnumerable(Of IndexedChild))
            If registeredChildLists Is Nothing Then
                registeredChildLists = New List(Of IEnumerable(Of IndexedChild))
            End If
            registeredChildLists.Add(pChildList)
        End Sub


        Public Function GetSchema() As XmlSchema Implements IXmlSerializable.GetSchema
            Return Nothing
        End Function

        Public Sub ReadXml(reader As XmlReader) Implements IXmlSerializable.ReadXml
            Throw New NotImplementedException()
        End Sub

        Public Sub WriteXml(writer As XmlWriter) Implements IXmlSerializable.WriteXml

            IndexedChild.WritePropertiesAsXml(writer, Me)

            For Each childList As IEnumerable(Of IndexedChild) In registeredChildLists
                IndexedChild.WriteAllXmlElements(writer, childList)
            Next

        End Sub

    End Class


    Public MustInherit Class IndexedChild
        Implements IXmlSerializable

        Public Shared Function WriteAllXmlElements(pWriter As XmlWriter, pList As IEnumerable(Of IndexedChild))
            For Each item As IXmlSerializable In pList
                pWriter.WriteStartElement(item.GetType.Name.ToString.ToLower + pList.ToList.IndexOf(item).ToString)
                item.WriteXml(pWriter)
                pWriter.WriteEndElement()
            Next
        End Function

        Public Shared Function WritePropertiesAsXml(pWriter As XmlWriter, pObj As Object)
            For Each prop As Reflection.PropertyInfo In pObj.GetType().GetProperties
                If Attribute.IsDefined(prop, GetType(XmlElementAttribute)) Then
                    pWriter.WriteElementString(prop.Name, prop.GetValue(pObj, Nothing))
                ElseIf Attribute.IsDefined(prop, GetType(XmlAttributeAttribute)) Then
                    pWriter.WriteAttributeString(prop.Name, prop.GetValue(pObj, Nothing))
                End If
            Next
        End Function

        Public Sub ReadXml(reader As XmlReader) Implements IXmlSerializable.ReadXml
            Throw New NotImplementedException
        End Sub

        Public Sub WriteXml(writer As XmlWriter) Implements IXmlSerializable.WriteXml
            WritePropertiesAsXml(writer, Me)
        End Sub

        Public Function GetSchema() As XmlSchema Implements IXmlSerializable.GetSchema
            Return Nothing
        End Function
    End Class

推荐阅读