6

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 は正しく解析されますが、問題は他のプロパティ (日時) の値が空であることです...

4

2 に答える 2

5

これが私がやっていることの出発点であり、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=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=アメリカ/シカゴ:20140711T133000\nDTEND;TZID=アメリカ/シカゴ: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);
}
于 2014-08-01T20:50:36.217 に答える
-1

これは、正規表現を使用する良い例です。一般的な解析のためにこれを試してください:

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

または、よりスキーマ固有のものを用意することもできます。

\s*(?:DTSTART:)(?'Start'\w+)
\s*(?:DTEND:)(?'End'\w+)
\s*(?:RRULE:)(?'Rule'(\w+=\w+;)+(\w+=\w+)?)
于 2011-07-09T20:56:27.443 に答える