1

我正在使用序列化创建 XML,当我需要为元素动态创建属性时遇到问题。我正在添加其中包含价格数据的日期元素。我的 XML 类结构如下所示:

 <XmlRoot(ElementName:="root")>
    Public Class DateXML
        <XmlElement(ElementName:="date")> _
        Public Property Dates As List(Of DatePrice)
    End Class

    Public Class DatePrice
        <XmlAttribute("value")> _
        Public Property DateValue As String
        <XmlElement("price")> _
        Public Property Price As String
    End Class

然后 XML 将如下所示:

<root>
    <date value="2013-01-01">
        <price>100.00</price>
    </date>
    <date value="2013-01-02">
        <price>100.00</price>
    </date>
    <date value="2013-01-03">
        <price>100.00</price>
    </date>
    <date value="2013-01-04">
        <price>100.00</price>
    </date>
    <date value="2013-01-08">
        <price>100.00</price>
    </date>
    <date value="2013-01-12">
        <price>100.00</price>
    </date>
</root>

我的问题是对 XML 的要求。如果我有多个价格相同的日期值,我应该使用value1="2013-01-01" value2="2013-01-02"etc 将它们放在一个节点中。此外,如果日期彼此跟随,我应该使用from="" to=""属性,并且允许混合这些属性。目标是使用属性创建尽可能少的日期节点。所以上面的例子应该是这样的:

<root>
    <date from="2013-01-01" to="2013-01-04">
        <price>100.00</price>
    </date>
    <date value1="2013-01-08" value2="2013-01-12">
        <price>100.00</price>
    </date>
</root>

我应该如何创建我的 DatePrice 类来完成这个要求?我正在从数据库中获取每个日期的数据。我可以将 from 和 to 属性作为属性添加到类中,但是是否可以为 value1、value2 ...动态添加属性?

编辑:

在发现如何序列化字典之后,我现在更接近了。这是我尝试过的:

<XmlRoot(ElementName:="root")>
Public Class XmlObject
    <XmlElement(ElementName:="element")> _
    Public Property element As String 
    Public Property elementAttributes As ValueAttributes
End Class

Public Class ValueAttributes
    Public Property values As SerializableDictionary(Of String, String)
End Class

实现 IXmlSerializable 的字典类:

Public Class SerializableDictionary(Of AttributeName, AttributeValue)
    Inherits Dictionary(Of String, String)
    Implements IXmlSerializable

    Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema
        Return Nothing
    End Function

    Public Sub ReadXml(reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml 
        If reader.HasAttributes Then
            While reader.MoveToNextAttribute()

                Dim key As String = reader.Name
                Dim value As String = reader.Value
                Me.Add(key, value)
            End While

            reader.MoveToElement()
        End If
    End Sub

    Public Sub WriteXml(writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml     
        For Each kvp As KeyValuePair(Of String, String) In Me
            writer.WriteAttributeString(kvp.Key, kvp.Value)
        Next
    End Sub

End Class

使用这些,我将得到一个如下所示的 XML:

<root>
  <element>the element value</element>
  <elementAttributes>
    <values value1="1" value2="2" value3="3" />
  </elementAttributes>
</root>

现在我只需要以某种方式弄清楚如何将属性移动到element而不是写入elementAttributes结构。

4

1 回答 1

0

将回答我自己的问题,因为我有一个我认为我现在可以接受的解决方案,或者至少尝试一下它是否足够。因此,为了创建节点并向它们动态添加属性,我创建了一个如下所示的类:

Public Class DateElement
    Implements IXmlSerializable

    Public Property DateValueAttributes As Dictionary(Of String, String)
    Public Property Price As String

    Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema
        Return Nothing
    End Function

    Public Sub ReadXml(reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml
        If reader.HasAttributes Then
            DateValueAttributes = New Dictionary(Of String, String)
            While reader.MoveToNextAttribute()
                DateValueAttributes.Add(reader.Name, reader.Value)
            End While

            reader.MoveToElement()
        End If

        Dim wasEmpty As Boolean = reader.IsEmptyElement
        reader.Read()

        If wasEmpty Then
            Return
        End If

        While reader.NodeType <> System.Xml.XmlNodeType.EndElement
            reader.ReadStartElement("price")
            Price = reader.ReadString()
            reader.ReadEndElement()
        End While

        reader.ReadEndElement()

    End Sub

    Public Sub WriteXml(writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml
        For Each kvp As KeyValuePair(Of String, String) In Me.DateValueAttributes
            writer.WriteAttributeString(kvp.Key, kvp.Value)
        Next

        If Price IsNot Nothing Then
            writer.WriteStartElement("price")
            writer.WriteString(Price)
            writer.WriteEndElement()
        End If

    End Sub
End Class

我可以在我的 xml 对象中使用这个类,例如:

<XmlRoot(ElementName:="root")>
Public Class XmlObject
    <XmlElement("date")>
    Public Property [element] As DateElement
End Class

然后在代码中创建对象,例如:

Dim xml As New XmlObject()
        xml.element = New DateElement()
        xml.element.DateValueAttributes = New Dictionary(Of String, String)
        xml.element.DateValueAttributes.Add("value1", "2013-01-01")
        xml.element.DateValueAttributes.Add("value2", "2013-01-02")
        xml.element.DateValueAttributes.Add("value3", "2013-01-03")
        xml.element.Price = "100.00"

将给出如下所示的结果 XML:

<root>
  <date value1="2013-01-01" value2="2013-01-02" value3="2013-01-03">
    <price>100.00</price>
  </date>
</root>

我想我现在已经足够近了,所以我可以处理这个问题。如果有人有任何想法,我将非常乐意听到他们的声音。

于 2013-01-25T08:31:19.763 回答