具有xml-element的xml-元素的XML序列化

问题描述 投票:0回答:2

我必须创建一个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”的属性。其次,“ Test”元素上有一个序列号。导入必须看起来像这样:

<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>

我如何实现这两个主题?

xml vb.net serialization xml-serialization xmlserializer
2个回答
0
投票

使用Xml Linq:

Imports System.Xml
Imports System.Xml.Linq
Module Module1
    Const FILENAME As String = "c:\temp\test.xml"
    Sub Main()
        Dim doc As XDocument = XDocument.Load(FILENAME)
        Dim xyz As Xyz = doc.Descendants("Xyz").Select(Function(x) New Xyz With { _
                                                        .id = CType(x.Attribute("id"), Integer), _
                                                        .name = CType(x.Element("Name"), String), _
                                                        .comment = CType(x.Element("Comment"), String), _
                                                        .block = CType(x.Element("Block"), String), _
                                                        .test = x.Elements().Where(Function(y) y.Name.LocalName.StartsWith("Test")).Select(Function(y) CType(y.Element("Name"), String)).ToList()
                                                    }).FirstOrDefault()

    End Sub

End Module
Public Class Xyz
    Property id As Integer
    Property name As String
    Property comment As String
    Property block As String
    Property test As List(Of String)

End Class

0
投票

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

我不明白,为什么我需要在父级使用IXMLSERIALIZER而在(索引)子级使用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
© www.soinside.com 2019 - 2024. All rights reserved.