XML serialize, который имел xml -атрибут xml -элементом - PullRequest
0 голосов
/ 09 апреля 2020

Мне нужно создать документ XML для импорта в другое программное обеспечение. Процесс импорта не может быть изменен, поэтому xml и его структура фиксированы.

Я работаю с VB. net в visualstudio. Я использую «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>

Как я могу реализовать эти две темы?

Ответы [ 2 ]

0 голосов
/ 14 апреля 2020

Мое решение вы видите ниже. Это работает для меня, но ...

Что я не понимаю, зачем мне нужен IXMLSERIALIZER в родительском классе и в (проиндексированном) дочернем классе. Я проверял иначе, но это не сработало. Everytime был, например, тегом «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
0 голосов
/ 09 апреля 2020

Использование 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...