Парсинг гугл календаря на DDay.iCal - PullRequest
6 голосов
/ 30 апреля 2011

Я работаю над приложением, которое анализирует Календарь Google через API Google для DDay.iCal

Основные атрибуты, свойства обрабатываются легко ... ev.Summary = evt.Title.Text;

Проблема в том, что когда я получил повторяющееся событие, XML содержит поле, подобное:

<gd:recurrence>
    DTSTART;VALUE=DATE:20100916
    DTEND;VALUE=DATE:20100917
    RRULE:FREQ=YEARLY
</gd:recurrence>

или

<gd:recurrence>
  DTSTART:20100915T220000Z
  DTEND:20100916T220000Z
  RRULE:FREQ=YEARLY;BYMONTH=9;WKST=SU"
</gd:recurrence>

используя следующий код:

    String[] lines = 
evt.Recurrence.Value.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (String line in lines)
                    {

                        if (line.StartsWith("R"))
                        {
                            RecurrencePattern rp = new RecurrencePattern(line);
                            ev.RecurrenceRules.Add(rp);
                        }
                        else 
                        {
                            ISerializationContext ctx = new SerializationContext();
                            ISerializerFactory factory = new DDay.iCal.Serialization.iCalendar.SerializerFactory();

                            ICalendarProperty property = new CalendarProperty();

                            IStringSerializer serializer = factory.Build(property.GetType(), ctx) as IStringSerializer;

                            property = (ICalendarProperty)serializer.Deserialize(new StringReader(line));

                            ev.Properties.Add(property);
                            Console.Out.WriteLine(property.Name + " - " + property.Value);
                        }

                    }

RRULE анализируются правильно, но проблема в том, что значения других свойств (datetime) пусты ...

Ответы [ 2 ]

4 голосов
/ 02 августа 2014

Вот отправная точка того, что я делаю, исходя из правила повторения спецификации RFC-5545 . Это не полная спецификация и может сломаться при определенных входных данных, но это должно помочь вам. Я думаю, что все это должно быть выполнимо с использованием RegEx, и что-то тяжелое, чем рекурсивный приличный парсер, будет излишним.

RRULE:(?:FREQ=(DAILY|WEEKLY|SECONDLY|MINUTELY|HOURLY|DAILY|WEEKLY|MONTHLY|YEARLY);)?(?:COUNT=([0-9]+);)?(?:INTERVAL=([0-9]+);)?(?:BYDAY=([A-Z,]+);)?(?:UNTIL=([0-9]+);)?

Я строю это, используя http://regexstorm.net/tester.

Используемый мной тестовый ввод:

DTSTART; TZID = Америка / Чикаго: 20140711T133000 \ nDTEND; TZID = Америка / Чикаго: 20140711T163000 \ nRRULE: FREQ = ЕЖЕНЕДЕЛЬНИК; ИНТЕРВАЛ = 8; BYDAY = FR, ПОКА = 20141101

DTSTART; TZID = Америка / Чикаго: 20140711T133000 \ nDTEND; TZID = Америка / Чикаго: 20140711T163000 \ nRRULE: FREQ = ЕЖЕНЕДЕЛЬНИК; COUNT = 5; ИНТЕРВАЛ = 8; BYDAY = FR, ПОКА = 20141101

DTSTART; TZID = Америка / Чикаго: 20140711T133000 \ nDTEND; TZID = Америка / Чикаго: 20140711T163000 \ nRRULE: FREQ = ЕЖЕНЕДЕЛЬНИК; BYDAY = FR, ПОКА = 20141101

Результаты сопоставления образцов будут выглядеть так:

Index    Position    Matched String                                                 $1      $2  $3  $4  $5
0        90          RRULE:FREQ=WEEKLY;INTERVAL=8;BYDAY=FR;UNTIL=20141101           WEEKLY      8   FR  20141101
1        236         RRULE:FREQ=WEEKLY;COUNT=5;INTERVAL=8;BYDAY=FR;UNTIL=20141101   WEEKLY  5   8   FR  20141101
2        390         RRULE:FREQ=WEEKLY;BYDAY=FR;UNTIL=20141101                      WEEKLY          FR  20141101

Использование как:

string freqPattern = @"RRULE:(?:FREQ=(DAILY|WEEKLY|SECONDLY|MINUTELY|HOURLY|DAILY|WEEKLY|MONTHLY|YEARLY);?)?(?:COUNT=([0-9]+);?)?(?:INTERVAL=([0-9]+);?)?(?:BYDAY=([A-Z,]+);?)?(?:UNTIL=([0-9]+);?)?";
MatchCollection mc = Regex.Matches(rule, freqPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
foreach (Match m in mc)
{
    string frequency = m.Groups[1].ToString();
    string count = m.Groups[2].ToString();
    string interval = m.Groups[3].ToString();
    string byday = m.Groups[4].ToString();
    string until = m.Groups[5].ToString();
    System.Console.WriteLine("recurrence => frequency: \"{0}\", count: \"{1}\", interval: \"{2}\", byday: \"{3}\", until: \"{4}\"", frequency, count, interval, byday, until);
}
0 голосов
/ 10 июля 2011

Это отличный пример того, когда использовать регулярные выражения.Попробуйте это для общего анализа:

\s*(\w+):((\w+=\w+;)+(\w+=\w+)?|\w+)

Или, возможно, вы решите использовать что-то более специфичное для схемы.

\s*(?:DTSTART:)(?'Start'\w+)
\s*(?:DTEND:)(?'End'\w+)
\s*(?:RRULE:)(?'Rule'(\w+=\w+;)+(\w+=\w+)?)
...