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 を使用してそれらを 1 つのノードに配置する必要があります。さらに、日付が互いに続く場合は、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 に答える