1# RELAX NG Schema for iCalendar in XML
2# Extract from RFC6321.
3# Erratum 3042 applied.
4# Erratum 3050 applied.
5# Erratum 3314 applied.
6
7default namespace = "urn:ietf:params:xml:ns:icalendar-2.0"
8
9# 3.2 Property Parameters
10
11# 3.2.1 Alternate Text Representation
12
13altrepparam = element altrep {
14    value-uri
15}
16
17# 3.2.2 Common Name
18
19cnparam = element cn {
20    value-text
21}
22
23# 3.2.3 Calendar User Type
24
25cutypeparam = element cutype {
26    element text {
27        "INDIVIDUAL" |
28        "GROUP" |
29        "RESOURCE" |
30        "ROOM" |
31        "UNKNOWN"
32    }
33}
34
35# 3.2.4 Delegators
36
37delfromparam = element delegated-from {
38    value-cal-address+
39}
40
41# 3.2.5 Delegatees
42
43deltoparam = element delegated-to {
44    value-cal-address+
45}
46
47# 3.2.6 Directory Entry Reference
48
49dirparam = element dir {
50    value-uri
51}
52
53# 3.2.7 Inline Encoding
54
55encodingparam = element encoding {
56    element text {
57        "8BIT" |
58        "BASE64"
59    }
60}
61
62# 3.2.8 Format Type
63
64fmttypeparam = element fmttype {
65    value-text
66}
67
68# 3.2.9 Free/Busy Time Type
69
70fbtypeparam = element fbtype {
71    element text {
72        "FREE" |
73        "BUSY" |
74        "BUSY-UNAVAILABLE" |
75        "BUSY-TENTATIVE"
76    }
77}
78
79# 3.2.10 Language
80
81languageparam = element language {
82    value-text
83}
84
85# 3.2.11 Group or List Membership
86
87memberparam = element member {
88    value-cal-address+
89}
90
91# 3.2.12 Participation Status
92
93partstatparam = element partstat {
94    type-partstat-event |
95    type-partstat-todo |
96    type-partstat-jour
97}
98
99type-partstat-event = (
100    element text {
101        "NEEDS-ACTION" |
102        "ACCEPTED" |
103        "DECLINED" |
104        "TENTATIVE" |
105        "DELEGATED"
106    }
107)
108
109type-partstat-todo = (
110    element text {
111        "NEEDS-ACTION" |
112        "ACCEPTED" |
113        "DECLINED" |
114        "TENTATIVE" |
115        "DELEGATED" |
116        "COMPLETED" |
117        "IN-PROCESS"
118    }
119)
120
121type-partstat-jour = (
122    element text {
123        "NEEDS-ACTION" |
124        "ACCEPTED" |
125        "DECLINED"
126    }
127)
128
129# 3.2.13 Recurrence Identifier Range
130
131rangeparam = element range {
132    element text {
133        "THISANDFUTURE"
134    }
135}
136
137# 3.2.14 Alarm Trigger Relationship
138
139trigrelparam = element related {
140    element text {
141        "START" |
142        "END"
143    }
144}
145
146# 3.2.15 Relationship Type
147
148reltypeparam = element reltype {
149    element text {
150        "PARENT" |
151        "CHILD" |
152        "SIBLING"
153    }
154}
155
156# 3.2.16 Participation Role
157
158roleparam = element role {
159    element text {
160        "CHAIR" |
161        "REQ-PARTICIPANT" |
162        "OPT-PARTICIPANT" |
163        "NON-PARTICIPANT"
164    }
165}
166
167# 3.2.17 RSVP Expectation
168
169rsvpparam = element rsvp {
170    value-boolean
171}
172
173# 3.2.18 Sent By
174
175sentbyparam = element sent-by {
176    value-cal-address
177}
178
179# 3.2.19 Time Zone Identifier
180
181tzidparam = element tzid {
182    value-text
183}
184
185# 3.3 Property Value Data Types
186
187# 3.3.1 BINARY
188
189value-binary =  element binary {
190    xsd:string
191}
192
193# 3.3.2 BOOLEAN
194
195value-boolean = element boolean {
196    xsd:boolean
197}
198
199# 3.3.3 CAL-ADDRESS
200
201value-cal-address = element cal-address {
202    xsd:anyURI
203}
204
205# 3.3.4 DATE
206
207pattern-date = xsd:string {
208    pattern = "\d\d\d\d-\d\d-\d\d"
209}
210
211value-date = element date {
212    pattern-date
213}
214
215# 3.3.5 DATE-TIME
216
217pattern-date-time = xsd:string {
218    pattern = "\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ?"
219}
220
221value-date-time = element date-time {
222    pattern-date-time
223}
224
225# 3.3.6 DURATION
226
227pattern-duration = xsd:string {
228    pattern = "(+|-)?P(\d+W)|(\d+D)?"
229            ~ "(T(\d+H(\d+M)?(\d+S)?)|"
230            ~   "(\d+M(\d+S)?)|"
231            ~   "(\d+S))?"
232}
233
234value-duration = element duration {
235    pattern-duration
236}
237
238# 3.3.7 FLOAT
239
240value-float = element float {
241    xsd:float
242}
243
244# 3.3.8 INTEGER
245
246value-integer = element integer {
247    xsd:integer
248}
249
250# 3.3.9 PERIOD
251
252value-period = element period {
253    element start {
254        pattern-date-time
255    },
256    (
257        element end {
258            pattern-date-time
259        } |
260        element duration {
261            pattern-duration
262        }
263    )
264}
265
266# 3.3.10 RECUR
267
268value-recur = element recur {
269    type-freq,
270    (type-until | type-count)?,
271    element interval {
272        xsd:positiveInteger
273    }?,
274    type-bysecond*,
275    type-byminute*,
276    type-byhour*,
277    type-byday*,
278    type-bymonthday*,
279    type-byyearday*,
280    type-byweekno*,
281    type-bymonth*,
282    type-bysetpos*,
283    element wkst { type-weekday }?
284}
285
286type-freq = element freq {
287    "SECONDLY" |
288    "MINUTELY" |
289    "HOURLY"   |
290    "DAILY"    |
291    "WEEKLY"   |
292    "MONTHLY"  |
293    "YEARLY"
294}
295
296type-until = element until {
297    type-date |
298    type-date-time
299}
300
301type-count = element count {
302    xsd:positiveInteger
303}
304
305type-bysecond = element bysecond {
306    xsd:nonNegativeInteger
307}
308
309type-byminute = element byminute {
310    xsd:nonNegativeInteger
311}
312
313type-byhour = element byhour {
314    xsd:nonNegativeInteger
315}
316
317type-weekday = (
318    "SU" |
319    "MO" |
320    "TU" |
321    "WE" |
322    "TH" |
323    "FR" |
324    "SA"
325)
326
327type-byday = element byday {
328    xsd:integer?,
329    type-weekday
330}
331
332type-bymonthday = element bymonthday {
333    xsd:integer
334}
335
336type-byyearday = element byyearday {
337    xsd:integer
338}
339
340type-byweekno = element byweekno {
341    xsd:integer
342}
343
344type-bymonth = element bymonth {
345    xsd:positiveInteger
346}
347
348type-bysetpos = element bysetpos {
349    xsd:integer
350}
351
352# 3.3.11 TEXT
353
354value-text = element text {
355    xsd:string
356}
357
358# 3.3.12 TIME
359
360pattern-time = xsd:string {
361    pattern = "\d\d:\d\d:\d\dZ?"
362}
363
364value-time = element time {
365    pattern-time
366}
367
368# 3.3.13 URI
369
370value-uri = element uri {
371    xsd:anyURI
372}
373
374# 3.3.14 UTC-OFFSET
375
376value-utc-offset = element utc-offset {
377    xsd:string { pattern = "(+|-)\d\d:\d\d(:\d\d)?" }
378}
379
380# UNKNOWN
381
382value-unknown = element unknown {
383    xsd:string
384}
385
386# 3.4 iCalendar Stream
387
388start = element icalendar {
389    vcalendar+
390}
391
392# 3.6 Calendar Components
393
394vcalendar = element vcalendar {
395    type-calprops,
396    type-component
397}
398
399type-calprops = element properties {
400    property-prodid &
401    property-version &
402    property-calscale? &
403    property-method?
404}
405
406type-component = element components {
407    (
408        component-vevent |
409        component-vtodo |
410        component-vjournal |
411        component-vfreebusy |
412        component-vtimezone
413    )*
414}
415
416# 3.6.1 Event Component
417
418component-vevent = element vevent {
419    type-eventprop,
420    element components {
421        component-valarm+
422    }?
423}
424
425type-eventprop = element properties {
426    property-dtstamp &
427    property-dtstart &
428    property-uid &
429
430    property-class? &
431    property-created? &
432    property-description? &
433    property-geo? &
434    property-last-mod? &
435    property-location? &
436    property-organizer? &
437    property-priority? &
438    property-seq? &
439    property-status-event? &
440    property-summary? &
441    property-transp? &
442    property-url? &
443    property-recurid? &
444
445    property-rrule? &
446
447    (property-dtend | property-duration)? &
448
449    property-attach* &
450    property-attendee* &
451    property-categories* &
452    property-comment* &
453    property-contact* &
454    property-exdate* &
455    property-rstatus* &
456    property-related* &
457    property-resources* &
458    property-rdate*
459}
460
461# 3.6.2 To-do Component
462
463component-vtodo = element vtodo {
464    type-todoprop,
465    element components {
466        component-valarm+
467    }?
468}
469
470type-todoprop = element properties {
471    property-dtstamp &
472    property-uid &
473
474    property-class? &
475    property-completed? &
476    property-created? &
477    property-description? &
478    property-geo? &
479    property-last-mod? &
480    property-location? &
481    property-organizer? &
482    property-percent? &
483    property-priority? &
484    property-recurid? &
485    property-seq? &
486    property-status-todo? &
487    property-summary? &
488    property-url? &
489
490    property-rrule? &
491
492    (
493        (property-dtstart?, property-dtend? ) |
494        (property-dtstart, property-duration)?
495    ) &
496
497    property-attach* &
498    property-attendee* &
499    property-categories* &
500    property-comment* &
501    property-contact* &
502    property-exdate* &
503    property-rstatus* &
504    property-related* &
505    property-resources* &
506    property-rdate*
507}
508
509# 3.6.3 Journal Component
510
511component-vjournal = element vjournal {
512    type-jourprop
513}
514
515type-jourprop = element properties {
516    property-dtstamp &
517    property-uid &
518
519    property-class? &
520    property-created? &
521    property-dtstart? &
522    property-last-mod? &
523    property-organizer? &
524    property-recurid? &
525    property-seq? &
526    property-status-jour? &
527    property-summary? &
528    property-url? &
529
530    property-rrule? &
531
532    property-attach* &
533    property-attendee* &
534    property-categories* &
535    property-comment* &
536    property-contact* &
537    property-description? &
538    property-exdate* &
539    property-related* &
540    property-rdate* &
541    property-rstatus*
542}
543
544# 3.6.4 Free/Busy Component
545
546component-vfreebusy = element vfreebusy {
547    type-fbprop
548}
549
550type-fbprop = element properties {
551    property-dtstamp &
552    property-uid &
553
554    property-contact? &
555    property-dtstart? &
556    property-dtend? &
557    property-duration? &
558    property-organizer? &
559    property-url? &
560
561    property-attendee* &
562    property-comment* &
563    property-freebusy* &
564    property-rstatus*
565}
566
567# 3.6.5 Time Zone Component
568
569component-vtimezone = element vtimezone {
570    element properties {
571        property-tzid &
572
573        property-last-mod? &
574        property-tzurl?
575    },
576    element components {
577        (component-standard | component-daylight) &
578        component-standard* &
579        component-daylight*
580    }
581}
582
583component-standard = element standard {
584    type-tzprop
585}
586
587component-daylight = element daylight {
588    type-tzprop
589}
590
591type-tzprop = element properties {
592    property-dtstart &
593    property-tzoffsetto &
594    property-tzoffsetfrom &
595
596    property-rrule? &
597
598    property-comment* &
599    property-rdate* &
600    property-tzname*
601}
602
603# 3.6.6 Alarm Component
604
605component-valarm = element valarm {
606    type-audioprop | type-dispprop | type-emailprop
607}
608
609type-audioprop = element properties {
610    property-action &
611
612    property-trigger &
613
614    (property-duration, property-repeat)? &
615
616    property-attach?
617}
618
619type-emailprop = element properties {
620    property-action &
621    property-description &
622    property-trigger &
623    property-summary &
624
625    property-attendee+ &
626
627    (property-duration, property-repeat)? &
628
629    property-attach*
630}
631
632type-dispprop = element properties {
633    property-action &
634    property-description &
635    property-trigger &
636
637    (property-duration, property-repeat)?
638}
639
640# 3.7 Calendar Properties
641
642# 3.7.1 Calendar Scale
643
644property-calscale = element calscale {
645
646    element parameters { empty }?,
647
648    element text { "GREGORIAN" }
649}
650
651# 3.7.2 Method
652
653property-method = element method {
654
655    element parameters { empty }?,
656
657    value-text
658}
659
660# 3.7.3 Product Identifier
661
662property-prodid = element prodid {
663
664    element parameters { empty }?,
665
666    value-text
667}
668
669# 3.7.4 Version
670
671property-version = element version {
672
673    element parameters { empty }?,
674
675    element text { "2.0" }
676}
677
678# 3.8 Component Properties
679
680# 3.8.1 Descriptive Component Properties
681
682# 3.8.1.1 Attachment
683
684property-attach = element attach {
685
686    element parameters {
687        fmttypeparam? &
688        encodingparam?
689    }?,
690
691    value-uri | value-binary
692}
693
694# 3.8.1.2 Categories
695
696property-categories = element categories {
697
698    element parameters {
699        languageparam? &
700    }?,
701
702    value-text+
703}
704
705# 3.8.1.3 Classification
706
707property-class = element class {
708
709    element parameters { empty }?,
710
711    element text {
712        "PUBLIC" |
713        "PRIVATE" |
714        "CONFIDENTIAL"
715    }
716}
717
718# 3.8.1.4 Comment
719
720property-comment = element comment {
721
722    element parameters {
723        altrepparam? &
724        languageparam?
725    }?,
726
727    value-text
728}
729
730# 3.8.1.5 Description
731
732property-description = element description {
733
734    element parameters {
735        altrepparam? &
736        languageparam?
737    }?,
738
739    value-text
740}
741
742# 3.8.1.6 Geographic Position
743
744property-geo = element geo {
745
746    element parameters { empty }?,
747
748    element latitude  { xsd:float },
749    element longitude { xsd:float }
750}
751
752# 3.8.1.7 Location
753
754property-location = element location {
755
756    element parameters {
757
758        altrepparam? &
759        languageparam?
760    }?,
761
762    value-text
763}
764
765# 3.8.1.8 Percent Complete
766
767property-percent = element percent-complete {
768
769    element parameters { empty }?,
770
771    value-integer
772}
773
774# 3.8.1.9 Priority
775
776property-priority = element priority {
777
778    element parameters { empty }?,
779
780    value-integer
781}
782
783# 3.8.1.10 Resources
784
785property-resources = element resources {
786
787    element parameters {
788        altrepparam? &
789        languageparam?
790    }?,
791
792    value-text+
793}
794
795# 3.8.1.11 Status
796
797property-status-event = element status {
798
799    element parameters { empty }?,
800
801    element text {
802        "TENTATIVE" |
803        "CONFIRMED" |
804        "CANCELLED"
805    }
806}
807
808property-status-todo = element status {
809
810    element parameters { empty }?,
811
812    element text {
813        "NEEDS-ACTION" |
814        "COMPLETED" |
815        "IN-PROCESS" |
816        "CANCELLED"
817    }
818}
819
820property-status-jour = element status {
821
822    element parameters { empty }?,
823
824    element text {
825        "DRAFT" |
826        "FINAL" |
827        "CANCELLED"
828    }
829}
830
831# 3.8.1.12 Summary
832
833property-summary = element summary {
834
835    element parameters {
836        altrepparam? &
837        languageparam?
838    }?,
839
840    value-text
841}
842
843# 3.8.2 Date and Time Component Properties
844
845# 3.8.2.1 Date/Time Completed
846
847property-completed = element completed {
848
849    element parameters { empty }?,
850
851    value-date-time
852}
853
854# 3.8.2.2 Date/Time End
855
856property-dtend = element dtend {
857
858    element parameters {
859        tzidparam?
860    }?,
861
862    value-date-time |
863    value-date
864}
865
866# 3.8.2.3 Date/Time Due
867
868property-due = element due {
869
870    element parameters {
871        tzidparam?
872    }?,
873
874    value-date-time |
875    value-date
876}
877
878# 3.8.2.4 Date/Time Start
879
880property-dtstart = element dtstart {
881
882    element parameters {
883        tzidparam?
884    }?,
885
886    value-date-time |
887    value-date
888}
889
890# 3.8.2.5 Duration
891
892property-duration = element duration {
893
894    element parameters { empty }?,
895
896    value-duration
897}
898
899# 3.8.2.6 Free/Busy Time
900
901property-freebusy = element freebusy {
902
903    element parameters {
904        fbtypeparam?
905    }?,
906
907
908    value-period+
909}
910
911# 3.8.2.7 Time Transparency
912
913property-transp = element transp {
914
915    element parameters { empty }?,
916
917    element text {
918        "OPAQUE" |
919        "TRANSPARENT"
920    }
921}
922
923# 3.8.3 Time Zone Component Properties
924
925# 3.8.3.1 Time Zone Identifier
926
927property-tzid = element tzid {
928
929    element parameters { empty }?,
930
931    value-text
932}
933
934# 3.8.3.2 Time Zone Name
935
936property-tzname = element tzname {
937
938    element parameters {
939        languageparam?
940    }?,
941
942    value-text
943}
944
945# 3.8.3.3 Time Zone Offset From
946
947property-tzoffsetfrom = element tzoffsetfrom {
948
949    element parameters { empty }?,
950
951    value-utc-offset
952}
953
954# 3.8.3.4 Time Zone Offset To
955
956property-tzoffsetto = element tzoffsetto {
957
958    element parameters { empty }?,
959
960    value-utc-offset
961}
962
963# 3.8.3.5 Time Zone URL
964
965property-tzurl = element tzurl {
966
967    element parameters { empty }?,
968
969    value-uri
970}
971
972# 3.8.4 Relationship Component Properties
973
974# 3.8.4.1 Attendee
975
976property-attendee = element attendee {
977
978    element parameters {
979        cutypeparam? &
980        memberparam? &
981        roleparam? &
982        partstatparam? &
983        rsvpparam? &
984        deltoparam? &
985        delfromparam? &
986        sentbyparam? &
987        cnparam? &
988        dirparam? &
989        languageparam?
990    }?,
991
992    value-cal-address
993}
994
995# 3.8.4.2 Contact
996
997property-contact = element contact {
998
999    element parameters {
1000        altrepparam? &
1001        languageparam?
1002    }?,
1003
1004    value-text
1005}
1006
1007# 3.8.4.3 Organizer
1008
1009property-organizer = element organizer {
1010
1011    element parameters {
1012        cnparam? &
1013        dirparam? &
1014        sentbyparam? &
1015        languageparam?
1016    }?,
1017
1018    value-cal-address
1019}
1020
1021# 3.8.4.4 Recurrence ID
1022
1023property-recurid = element recurrence-id {
1024
1025    element parameters {
1026        tzidparam? &
1027        rangeparam?
1028    }?,
1029
1030    value-date-time |
1031    value-date
1032}
1033
1034# 3.8.4.5 Related-To
1035
1036property-related = element related-to {
1037
1038    element parameters {
1039        reltypeparam?
1040    }?,
1041
1042    value-text
1043}
1044
1045# 3.8.4.6 Uniform Resource Locator
1046
1047property-url = element url {
1048
1049    element parameters { empty }?,
1050
1051    value-uri
1052}
1053
1054# 3.8.4.7 Unique Identifier
1055
1056property-uid = element uid {
1057
1058    element parameters { empty }?,
1059
1060    value-text
1061}
1062
1063# 3.8.5 Recurrence Component Properties
1064
1065# 3.8.5.1 Exception Date/Times
1066
1067property-exdate = element exdate {
1068
1069    element parameters {
1070        tzidparam?
1071    }?,
1072
1073    value-date-time+ |
1074    value-date+
1075}
1076
1077# 3.8.5.2 Recurrence Date/Times
1078
1079property-rdate = element rdate {
1080
1081    element parameters {
1082        tzidparam?
1083    }?,
1084
1085    value-date-time+ |
1086    value-date+ |
1087    value-period+
1088}
1089
1090# 3.8.5.3 Recurrence Rule
1091
1092property-rrule = element rrule {
1093
1094    element parameters { empty }?,
1095
1096    value-recur
1097}
1098
1099# 3.8.6 Alarm Component Properties
1100
1101# 3.8.6.1 Action
1102
1103property-action = element action {
1104
1105    element parameters { empty }?,
1106
1107    element text {
1108        "AUDIO" |
1109        "DISPLAY" |
1110        "EMAIL"
1111    }
1112}
1113
1114# 3.8.6.2 Repeat Count
1115
1116property-repeat = element repeat {
1117
1118    element parameters { empty }?,
1119
1120    value-integer
1121}
1122
1123# 3.8.6.3 Trigger
1124
1125property-trigger = element trigger {
1126
1127    (
1128        element parameters {
1129            trigrelparam?
1130        }?,
1131
1132        value-duration
1133    ) |
1134    (
1135        element parameters { empty }?,
1136
1137        value-date-time
1138    )
1139}
1140
1141# 3.8.7 Change Management Component Properties
1142
1143# 3.8.7.1 Date/Time Created
1144
1145property-created = element created {
1146
1147    element parameters { empty }?,
1148
1149    value-date-time
1150}
1151
1152# 3.8.7.2 Date/Time Stamp
1153
1154property-dtstamp = element dtstamp {
1155
1156    element parameters { empty }?,
1157
1158    value-date-time
1159}
1160
1161# 3.8.7.3 Last Modified
1162
1163property-last-mod = element last-modified {
1164
1165    element parameters { empty }?,
1166
1167    value-date-time
1168}
1169
1170# 3.8.7.4 Sequence Number
1171
1172property-seq = element sequence {
1173
1174    element parameters { empty }?,
1175
1176    value-integer
1177}
1178
1179# 3.8.8 Miscellaneous Component Properties
1180
1181# 3.8.8.3 Request Status
1182
1183property-rstatus = element request-status {
1184
1185    element parameters {
1186        languageparam?
1187    }?,
1188
1189    element code { xsd:string },
1190    element description { xsd:string },
1191    element data { xsd:string }?
1192}
1193