2011-04-30 163 views
5

我工作的應用程序,它通過谷歌API解析谷歌日曆DDay.iCal解析谷歌日曆DDay.iCal

主要屬性,屬性很容易 ... ev.Summary = evt.Title處理。文本;

問題是,當我得到了一個重複事件中,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); 
         } 

        } 

RRULEs被正確解析,但問題在於其他屬性(d有時)值爲空...

+0

您的意思是使用DTSTART和DTEND冒號後您的第一個例子嗎?在第二個例子中SU之後是否意味着一個雙引號? – 2011-07-09 20:43:34

回答

4

下面是我在做什麼,都會響起的the RFC-5545 spec's recurrence rule的起點。對規範並不完整,可能會因爲某些輸入而中斷,但它應該會讓你繼續。我認爲這應該都可以使用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 = WEEKLY; INTERVAL = 8; BYDAY = FR; UNTIL = 20141101

DTSTART; TZID =美國/芝加哥:20140711T133000 \ nDTEND; TZID =美國/芝加哥:20140711T163000 \ nRRULE:FREQ = WEEKLY; COUNT = 5; INTERVAL = 8; BYDAY = FR; UNTIL = 20141101

DTSTART; TZID = America/Chicago:20140711T133000 \ nDTEND; TZID = America/Chicago:20140711T163000 \ nRRULE:FREQ = WEEKLY; BYDAY = FR; UNTIL = 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); 
} 
-1

這是一個很好的使用正則表達式的例子。嘗試了這一點一般解析:

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

或者,你可能會決定有更多的東西架構特定的。

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