B4J Question Parsing ICS (icalendar file)

ivanomonti

Expert
Licensed User
Longtime User
Erel, here you find documentation on the standard ical (ics) standard file calendars http://icalendar.readthedocs.io/en/latest/usage.html

B4X:
'    BEGIN:VEVENT
'    DTSTART:20170225T110000Z
'    DTEND:20170225T120000Z
'    DTSTAMP:20170925T183859Z
'    UID:[email protected]
'    CREATED:20170224T193338Z
'    DESCRIPTION:Al momento n.i.
'    LAST-MODIFIED:20170225T113653Z
'    LOCATION:
'    SEQUENCE:1
'    STATUS:CONFIRMED
'    SUMMARY:[02757207] S1  FOTOVOLTAICO RESIDENZIALE -  CORRADO RIVA (036291996
'    7//) - CASCINA BOSCACCIO\, 10\, 20844 TRIUGGIO (MB) - 3928566640 parlato co
'    n il sigr corrado requisiti ok ha gia fatto delle consulenze per il fotovol
'    taico ma mai con noi
'    TRANSP:OPAQUE
'    BEGIN:VALARM
'    ACTION:DISPLAY
'    DESCRIPTION:This Is an event reminder
'    TRIGGER:-P0DT0H30M0S
'    End:VALARM
'    End:VEVENT
 
Upvote 0

ivanomonti

Expert
Licensed User
Longtime User
Another option is parse the file as it is (it's a text file and doesn't seem too complicated to parse (without a library))

to analyze it is not complicated, but I have to collect data and insert it into a database, the DESCRIPTION field if it has a multiple-line note without a parse, destroys the sequence and the data becomes illegible
 
Upvote 0

ivanomonti

Expert
Licensed User
Longtime User
Erel, here you have the original files, one converted to simple txt
 

Attachments

  • iCal.zip
    47.2 KB · Views: 178
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Create a class named ICSParser with this code:
B4X:
'Class module
Sub Class_Globals
   Type ICSObject (TypeName As String, Attributes As Map, Children As List)
   Private LineIndex As Int
   Private Lines As List
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
   
End Sub

Public Sub Parse(Dir As String, FileName As String) As ICSObject
   Lines = File.ReadList(Dir, FileName)
   LineIndex = 0
   Dim kv() As String = ReadNextLine
   If kv(0) <> "BEGIN" Then
     LogError("Invalid file")
     Return Null
   End If
   Dim root As ICSObject = CreateICS(kv(1))
   ParseICS(root)
   Return root
End Sub

Private Sub ReadNextLine As String()
   Dim first As String = Lines.Get(LineIndex)
   LineIndex = LineIndex + 1
   Do While LineIndex < Lines.Size - 1
     Dim NextLine As String = Lines.Get(LineIndex)
     If NextLine.StartsWith(" ") Then
       LineIndex = LineIndex + 1
       first = first & NextLine
     Else
       Exit
     End If
   Loop
   first = first.Replace("\n", CRLF)
   Dim i As String = first.IndexOf(":")
   Return Array As String(first.SubString2(0, i), first.SubString(i + 1))
End Sub

Private Sub ParseICS (parent As ICSObject) As ICSObject
   Do While True
     Dim kv() As String = ReadNextLine
     If kv(0) = "BEGIN" Then
       parent.Children.Add(ParseICS(CreateICS(kv(1))))
     Else If kv(0) = "END" Then
       Exit
     Else
       parent.Attributes.Put(kv(0), kv(1))
     End If
   Loop
   Return parent
End Sub

Private Sub CreateICS (TypeName As String) As ICSObject
   Dim ic As ICSObject
   ic.Initialize
   ic.TypeName = TypeName
   ic.Children.Initialize
   ic.Attributes.Initialize
   Return ic
End Sub

Public Sub PrintTree(Parent As ICSObject, Indent As String)
   Log($"${Indent}******* ${Parent.TypeName} *******"$)
   For Each key As String In Parent.Attributes.Keys
     Log($"${Indent}${key}: ${Parent.Attributes.Get(key)}"$)
   Next
   For Each ics As ICSObject In Parent.Children
     PrintTree(ics, Indent & TAB)
   Next
End Sub

Usage:
B4X:
Dim parser As ICSParser
parser.Initialize
Dim root As ICSObject = parser.Parse(File.DirAssets, "iCal.ics")
parser.PrintTree(root, "")
 
Upvote 0
Top