0

I have below custom class:

Public Class Frame

#Region " Enumerations "

    Public Enum FrameResult
        Success
        Failed
    End Enum

#End Region

#Region " Private Members "

    Private _timeStamp As Date
    Private _content As String
    Private _result As String

#End Region

#Region " Constructors "

    Sub New(ByVal timeStamp As Date, ByVal content As String, ByVal result As FrameResult)
        Me._timeStamp = timeStamp
        Me._content = content
        Me._result = result.ToString
    End Sub

#End Region

#Region " Properties "

    Public Property TimeStamp() As Date
        Get
            Return Me._timeStamp
        End Get

        Set(ByVal value As Date)
            Me._timeStamp = value
        End Set
    End Property

    Public Property Content() As String
        Get
            Return Me._content
        End Get

        Set(ByVal value As String)
            Me._content = value
        End Set
    End Property


    Public Property Result() As FrameResult
        Get
            Return DirectCast([Enum].Parse(GetType(FrameResult), Me._result), FrameResult)
        End Get

        Set(ByVal value As FrameResult)
            Me._result = value.ToString
        End Set
    End Property

#End Region


End Class

And I am trying to add multiple xElements at once to a XML document depending on if xml file exists or not:

Public Sub Add(ByVal frameData() as Frame) {

     if FileExists(xmlFile) then
        ' XML File exists

        xElem = XElement.Load(xmlFile)
        xElem.Add(frameData) --> not working

        ' Persist changes to file. Save to Disk
        xElem.Save(xmlFile)

     else
         ' File does not exist

        xDoc = New XDocument(New XDeclaration("1.0", "UTF-8", Nothing))
        xDoc.Root.Add(frameData)       

        sw = New StringWriter()
        xWrite = XmlWriter.Create(sw)

        xDoc.Save(xWrite)
        xWrite.Close()

        ' Persist changes to file. Save to Disk
        xDoc.Save(xmlFile)

     End If

But it does not work. I have tried to do:

       Dim _frame as Frame

       xDoc = New XDocument(New XDeclaration("1.0", "UTF-8", Nothing), _
        new XElement("Frames", _
        from _frame in frameData <--- not working, needs implements IQueryable
         select new XElement("TimeStamp", _frame.TimeStamp), _
            new XElement("Content", _frame.Content), _
            new XElement("Result", _frame.Result)))

but it does not work as frameData does not implements IQueryable and it seems so difficult... is there any other easy way?

My xml file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<frames>
    <frame>
        <timestamp>20/10/2016 07:30:05 AM</timestamp>
        <content>bla bla bla </content>
        <status>OK</status>
    </frame>
    <frame>
        <timestamp>20/10/2016 15:10:12 PM</timestamp>
        <content>bla bla bla </content>
        <status>FAIL</status>
    </frame>

    ... NEXT FRAMES ...

</frames>
Willy
  • 9,848
  • 22
  • 141
  • 284

1 Answers1

1

I would use XML Literals, which allow you to embed expressions to build up your XML from your objects. It seems more natural to me than all those nested New XElement. e.g.

Dim frameData = {
    New Frame(Date.Now, "A", Frame.FrameResult.Success),
    New Frame(Date.Now, "B", Frame.FrameResult.Success),
    New Frame(Date.Now, "C", Frame.FrameResult.Failed),
    New Frame(Date.Now, "D", Frame.FrameResult.Success),
    New Frame(Date.Now, "E", Frame.FrameResult.Success),
    New Frame(Date.Now, "F", Frame.FrameResult.Success)
}

Dim xml As XDocument = <?xml version="1.0" encoding="UTF-8"?><frames></frames>

Dim frames As IEnumerable(Of XElement) =
    From f In frameData
    Select <frame>
               <timestamp><%= f.TimeStamp %></timestamp>
               <content><%= f.Content %></content>
               <status><%= If(f.Result = Frame.FrameResult.Success, "OK", "FAIL") %></status>
           </frame>

xml.Root.Add(frames)

However, your comment about "not working, needs implements IQueryable" makes me wonder if you are missing a reference/import to something... or if I am missing something.

Mark
  • 8,140
  • 1
  • 14
  • 29
  • Yes, I agree. Even using XML Literals is more readable, but the disadvantage is that it introduces dependencies with start/end tags and if in a future XML start/end tags change it requires to update all them. I have tried to replace them by constants to avoid this, but this does not work. Anyway, you are right, I was missing the import: "imports System.Linq". Your solution also works. Thanks very much for your great example ;) – Willy Feb 23 '16 at 09:18