我正在创建一个带序列化的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"
等将它们放在一个节点中。此外,如果日期相互关联,我应该使用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
结构。
答案 0 :(得分: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>
我认为我现在已经足够接近,所以我可以解决这个问题。如果有人有任何想法,我会非常乐意听到他们。