forked from xsf/xeps
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxep-0284.xml
1071 lines (1038 loc) · 44.3 KB
/
xep-0284.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM "xep.ent">
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Shared XML Editing</title>
<abstract>This specification defines a protocol that enables two or more endpoints to collaboratively edit an XML object. The protocol is intended for use mainly over the Extensible Messaging and Presence Protocol (XMPP), either by existing instant messaging clients or by specialized editing clients. However, the protocol could also be used over a direct TCP connection rather than over XMPP.</abstract>
&LEGALNOTICE;
<number>0284</number>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
<spec>XMPP IM</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>NOT YET ASSIGNED</shortname>
<author>
<firstname>Joonas</firstname>
<surname>Govenius</surname>
<email>[email protected]</email>
<jid>[email protected]</jid>
</author>
&stpeter;
<author>
<firstname>Tom</firstname>
<surname>Pusateri</surname>
<email>[email protected]</email>
</author>
<revision>
<version>0.1.3</version>
<date>2021-03-04</date>
<initials>mw</initials>
<remark><p>Cross-document editorial adjustments for inclusive language.</p></remark>
</revision>
<revision>
<version>0.1.2</version>
<date>2019-11-23</date>
<initials>egp</initials>
<remark><ul>
<li>Add missing <state/> wrapper in example.</li>
<li>Fix duplicated new element in example.</li>
<li>Fix indentation.</li>
</ul></remark>
</revision>
<revision>
<version>0.1.1</version>
<date>2019-02-20</date>
<initials>ka</initials>
<remark><p>Fix use of incorrect namespace in examples</p></remark>
</revision>
<revision>
<version>0.1</version>
<date>2010-07-02</date>
<initials>psa</initials>
<remark><p>Initial published version.</p></remark>
</revision>
<revision>
<version>0.0.10</version>
<date>2010-06-08</date>
<initials>tp/psa</initials>
<remark><p>Updated Jingle namespaces, transport definitions, reason codes, and other syntax; improved feature discovery and session advertisement; updated namespace to be urn:xmpp:sxe:0 for future-compatibility.</p></remark>
</revision>
<revision>
<version>0.0.9</version>
<date>2009-12-04</date>
<initials>psa</initials>
<remark><p>Added session signalling via presence.</p></remark>
</revision>
<revision>
<version>0.0.8</version>
<date>2008-01-29</date>
<initials>psa/jg</initials>
<remark>
<ul>
<li>Modified negotiation protocol to use Jingle.</li>
<li>Defined Jingle transport method.</li>
</ul>
</remark>
</revision>
<revision>
<version>0.0.7</version>
<date>2008-01-24</date>
<initials>jg</initials>
<remark>
<ul>
<li>Added the "Example Session" section.</li>
<li>Clarification of the 'last-sender' and 'last-id' attributes.</li>
<li>Changed the definition of the "state".</li>
<li>Changed "SHOULD [abort the negotiation with others who offered the state]" to a "MUST" after one offer has been accepted.</li>
</ul>
</remark>
</revision>
<revision>
<version>0.0.6</version>
<date>2008-01-20</date>
<initials>jg</initials>
<remark>
<ul>
<li>Wording changes.</li>
<li>Added a paragraph about "maintaining an unordered set of records" to the introduction.</li>
<li>Renamed "node id" to "record id".</li>
<li>Renamed "metadata" to "record".</li>
<li>Renamed <configure/> to <set/>.</li>
<li>Renamed "node edits" to non-commutative edits.</li>
<li>Simplified the explanation of processing edits by creating a section "Mapping the Records to the DOM Document" and concentrating on the changes to the records in section "Commutative and Non-commutative edits".</li>
<li>Added the description of the <prolog/> element.</li>
<li>Replaced the <last-sxde/> element with 'last-sender' and 'last-id' attributes.</li>
<li>Added the 'replacefrom' and 'replacen' attributes.</li>
<li>Replaced the <in-session/> element with the <alternative-session/> element.</li>
</ul>
</remark>
</revision>
<revision>
<version>0.0.5</version>
<date>2007-08-30</date>
<initials>jg</initials>
<remark>
<ul>
<li>Renamed 'z' to 'weight'.</li>
<li>Moved the metadata (node id, primary-weight) out of the DOM. I.e. they are no longer attributes of elements; it is up to the implementation to how the metadata is stored.</li>
<li>Changed "element edits" to "node edits". Now each DOM node is required to have a GUID and can be modified separately. All nodes are arranged by their weight which removes the previous problems with mixed content.</li>
<li>Modified the examples accordingly.</li>
<li>Improved the glossary definitions.</li>
</ul>
</remark>
</revision>
<revision>
<version>0.0.4</version>
<date>2007-03-26</date>
<initials>jg</initials>
<remark><p>Wording changes. Changes to how set content/move element conflict is handled.</p></remark>
</revision>
<revision>
<version>0.0.3</version>
<date>2007-01-09</date>
<initials>jg</initials>
<remark>
<ul>
<li>Simplified the process for joining a session. Removed the notion of history being different from state in the context of joining.</li>
<li>Moved responsibility of undoing other users' conflicting edits to the server if one exists.</li>
<li>Added "XML Document Requirements" section.</li>
<li>Added that changes should be checked against the XSD of the document.</li>
<li>Renamed 'hash' attribute as 'id'.</li>
<li>Changed the format of the <feature/> elements.</li>
<li>Modified negotiation abortion reason.</li>
<li>Removed the XSD for now.</li>
<li>Removed the "Security Considerations" for now.</li>
<li>JEP to XEP.</li>
</ul>
</remark>
</revision>
<revision>
<version>0.0.2</version>
<date>2006-08-28</date>
<initials>jg</initials>
<remark><p>Initial version of the SXdE proposal after splitting the previous whiteboarding proposal.</p></remark>
</revision>
<revision>
<version>0.0.1</version>
<date>2006-06-19</date>
<initials>jg</initials>
<remark><p>Initial version.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>This specification defines a protocol for collaboratively editing XML data. Essentially, this protocol provides a simple way of synchronizing an unordered set of records across several endpoints. Additionally, this protocol defines a mapping between such a set of records and the Document Object Model (DOM).</p>
<p>A special feature of this protocol compared to most other collaborative editing tools is that no central or server entity is required. A &xep0045; component or specialized editing component can be used for sessions that have a large number of participants, that need to be persistent, or that require more granular access control. However, the client implementation is minimally different whether such a specialized component is used or whether the session is one-to-one or multi-user.</p>
</section1>
<section1 topic='Requirements' anchor='reqs'>
<p>Requirements for shared editing are provided in &xep0228;.</p>
</section1>
<section1 topic='Glossary' anchor='glossary'>
<p>GUID: a Globally Unique Indentifier, used as the identifier for a shared editing session.</p>
<p>Host: The JID to which the SXE messages are sent for relaying to other members of the session; this can be the initiator of the session (e.g., in a one-to-one session or small multi-user session) or a multi-user chat room or specialized shared editing component.</p>
<p>RID: the Record ID given to a record when it is created.</p>
<p>State: In the context of a new user joining, the state refers to the set of records that describes the edited object, including all previous versions of each record. All entities involved in the session are REQUIRED to keep this state unless a specialized component handles user joins.</p>
<p>Weight: Primarily, the weight of a node is represented by the 'primary-weight' field of the corresponding record. Secondarily, if the values of the 'primary-weight' of two records are equal, the first differing characters of the rids are compared by their Unicode values. The higher the character the higher the weight of the node is.</p>
</section1>
<section1 topic='Session Management' anchor='jingle'>
<p>When used in the context of XMPP, Shared XML Editing relies on &xep0166; for overall session management. In Jingle terms, SXE defines a "transport method" that can be used for multiple "application types" such as XHTML documents, SVG whiteboards, &xep0204;, or any other XML data format.</p>
<section2 topic='Initiation' anchor='jingle-initiate'>
<p>In order to initiate a shared editing session, one party sends a Jingle session-initiate request to another party. Here the <transport/> element indicates support for exchanging SXE information over XMPP and the <description/> element indicates support for editing of XHTML documents (this application type has not been defined yet and is used here only as an example). The <transport/> element MUST include at least one <host/> element that specifies the entity that serves as the host for the session. The host can be the initiator of the session (and must be for a one-to-one session) or a multi-user chat room or specialized reflector where the session is hosted.</p>
<example caption="Initiator sends session-initiate"><![CDATA[
<iq from='[email protected]/castle'
id='jingle1'
to='[email protected]/castle'
type='set'>
<jingle xmlns='urn:xmpp:jingle:1'
action='session-initiate'
initiator='[email protected]/castle'
sid='851ba2'>
<content creator='initiator' name='this-is-the-editing-content'>
<description xmlns='urn:xmpp:jingle:apps:xhtml'/>
<transport xmlns='urn:xmpp:jingle:transports:sxe'>
<host>[email protected]</host>
</transport>
</content>
</jingle>
</iq>
]]></example>
<p>The responder immediately acknowledges receipt of the session-initiate.</p>
<example caption="Responder acknowledges session-initiate"><![CDATA[
<iq from='[email protected]/castle'
id='jingle1'
to='[email protected]/castle'
type='result'/>
]]></example>
</section2>
<section2 topic='Session Acceptance' anchor='jingle-accept'>
<p>In order to definitively accept the session, the responder sends a session-accept to the initiator.</p>
<example caption="Responder sends session-accept"><![CDATA[
<iq from='[email protected]/castle'
id='jingle2'
to='[email protected]/castle'
type='set'>
<jingle xmlns='urn:xmpp:jingle:1'
action='session-accept'
initiator='[email protected]/castle'
sid='851ba2'>
<content creator='initiator' name='this-is-the-editing-content'>
<description xmlns='urn:xmpp:jingle:apps:xhtml'/>
<transport xmlns='urn:xmpp:jingle:transports:sxe'>
<host>[email protected]</host>
</transport>
</content>
</jingle>
</iq>
]]></example>
<p>The initiator immediately acknowledges receipt of the session-accept.</p>
<example caption="Initiator acknowledges session-accept"><![CDATA[
<iq from='[email protected]/castle'
id='jingle2'
to='[email protected]/castle'
type='result'/>
]]></example>
</section2>
<section2 topic='Session Refusal' anchor='jingle-decline'>
<p>In order to decline the session, the responder sends a session-terminate to the initiator.</p>
<example caption="Responder sends session-terminate"><![CDATA[
<iq from='[email protected]/castle'
id='jingle3'
to='[email protected]/castle'
type='set'>
<jingle xmlns='urn:xmpp:jingle:1'
action='session-terminate'
host='[email protected]'
initiator='[email protected]/castle'
sid='851ba2'>
<reason>
<unsupported-applications/>
</reason>
</jingle>
</iq>
]]></example>
<p>The responder indiciates the reason for refusing the session by including a "reason" element. The following reasons are suggested (see also <cite>XEP-0166</cite>):</p>
<ul>
<li>alternative-session -- the responder already has an active session with the initiator and wishes to use that session instead.</li>
<li>decline -- the responder formally declines the session.</li>
<li>unsupported-applications -- the responder supports none of the offered the application types.</li>
</ul>
<p>The initiator immediately acknowledges receipt of the session-terminate.</p>
<example caption="Initiator acknowledges session-terminate"><![CDATA[
<iq from='[email protected]/castle'
id='jingle3'
to='[email protected]/castle'
type='result'/>
]]></example>
</section2>
</section1>
<section1 topic='Determining the features of the Host' anchor='host'>
<p>Before connecting to a session, a party MUST determine the &xep0030; identity and supported features of the host. In many situations the party already knows this information (e.g., if the host is the initiator of the Jingle session). In other situations the party will need to send a service discovery information request to the host.</p>
<example caption='Service Discovery Request'><![CDATA[
<iq from='[email protected]/castle'
to='[email protected]/castle'
id='disco1'>
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<p>If the host supports Shared XML Editing over XMPP, it MUST return features of "urn:xmpp:sxe:0" and "urn:xmpp:jingle:transports:sxe" &NSNOTE;:</p>
<example caption='Service discovery response'><![CDATA[
<iq from='[email protected]/castle' to='[email protected]/castle' type='result' id='disco1'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity category='client' type='pc'/>
...
<feature var='urn:xmpp:sxe:0'/>
<feature var='urn:xmpp:jingle:transports:sxe'/>
...
</query>
</iq>
]]></example>
</section1>
<section1 topic='Advertising a Session' anchor='advertise'>
<p>An entity that is engaged in a session can advertise that fact by including the session id and descriptive name in its XMPP presence.</p>
<example caption='Advertising a session'><![CDATA[
<presence from='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0' session='851ba2' name='Marketing Materials'/>
</presence>
]]></example>
<p>Such presence can be broadcast or can be sent in the context of a multi-user chat room (see <cite>XEP-0045</cite>).</p>
<p>However, presence is not sent when operating in a serverless messaging environment (see <cite>XEP-0174</cite>). Instead, DNS TXT records are published. Two new key-value pairs are used to advertise a session id ("sxe_id") and session name ("sxe_name") when using serverless messaging.</p>
</section1>
<section1 topic='Connecting to a Session' anchor='connect'>
<p>In order to synchronize its local state with the existing state of the edited object, an entity sends a connection request to the host. The identity learned through service discovery determines what kind of message the joining party sends (e.g., type='groupchat' if the host is a MUC room).</p>
<p>To connect to a session, the joiner MUST send an SXE <connect/> element to the host.</p>
<example caption='Connecting to a session'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0' id='e' session='851ba2'>
<connect/>
</sxe>
</message>
]]></example>
</section1>
<section1 topic='Initial State Synchronization'>
<section2 topic='Making a State Offer'>
<p>When a joining user sends a connect request, the joiner must retrieve the state of the session from an existing participant. The following ruules apply:</p>
<ol>
<li>In a one-to-one session, the initiator MUST offer to send the state.</li>
<li>In a multi-user session, both the host and the invitor (initiator) MUST offer to send the state. However, other participants MAY offer to send the state. The joiner SHOULD prefer to receive the state from the host or initiator.</li>
</ol>
<p>The state offer MUST contain the <description/> element or elements that were included in the Jingle session-initiate request.</p>
<example caption='A state offer'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='f'>
<state-offer>
<description xmlns='urn:xmpp:jingle:apps:xhtml'/>
</state-offer>
</sxe>
</message>
]]></example>
</section2>
<section2 topic='Accepting a State Offer'>
<p>The joiner accepts a state offer by sending an <accept-state/> element to one of the entities that offer to send the state. The joiner MUST store all the <sxe/> elements it receives after the <state-offer/> element it decides to accept. It MUST also abort the negotiation with the other users that offered to send the state.</p>
<p>Once the other entity receives the <accept-state/> element it MUST proceed sending the state as described in the next section.</p>
<example caption='Accepting a state offer'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='g'>
<accept-state/>
</sxe>
</message>
]]></example>
</section2>
<section2 topic='Refusing a State Offer'>
<p>If a multiple state offers were received, one should be accepted and the others should be refused by sending a <refuse-state/> element.</p>
<example caption='Refusing a state offer'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='g'>
<refuse-state/>
</sxe>
</message>
]]></example>
</section2>
<section2 topic='Sending the State of the Document' >
<p>The process of sending the state is following:</p>
<ol>
<li>The sender sends a <document-begin/> element and simultaneously takes a "snapshot" of the document's state. The <document-begin/> element SHOULD have a 'prolog' attribute. The 'prolog' attribute should contain the XML prolog of the document encoded using the data: URI scheme (RFC 2397).</li>
<li>The sender sends the state as it was at the time of sending <document-begin/>.</li>
<li>The sender sends a <document-end/> element.</li>
</ol>
<p>The state can be sent in any number of <sxe/> elements but the user sending the state MUST NOT send any new <sxe/> elements between sending the <document-begin/> (i.e. taking the snapshot) and the <document-end/> element.</p>
<p>The state SHOULD include a version of each element that was synchronized, and hence won't be undone, as well as all the later versions. In practice this can often be impossible to know in a session without a specialized MUC component so it may be safest to send version 0 and all the later edits to each element. Version 0 is implied if the version element is missing.</p>
<example caption='Sending the state of a blank document (only prolog)'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='b'>
<state>
<document-begin
prolog='data:text/xml,%3C%3Fxml%20version%3D%271.\
0%27%20standalone%3D%27no%27%3F%3E%0A%3C%21DOCTYPE%20svg%\
20PUBLIC%20%27-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%27%\
20%27http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD\
%2Fsvg11.dtd%27%3E%0A'/>
<document-end last-sender='' last-id='' />
</state>
</sxe>
</message>
]]></example>
<p>If the session is already in progress, the entity sends the snapshot.</p>
<example caption='Sending the state of an existing document'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='bxyz'>
<state>
<document-begin
prolog='data:text/xml,%3C!DOCTYPE%20html%0D%0APUBLIC%20%22-\
%2F%2FW3C%2F%2FDTD%20XHTML%201.0%20Strict%2F%2FEN%22%0D%0A%22htt\
p%3A%2F%2Fwww.w3.org%2FTR%2Fxhtml1%2FDTD%2Fxhtml1-strict.dtd%223\
E%0D%0A'/>
<new type='processinginstruction'
pitarget='xml-stylesheet'
pidata='href="style.xsl" type="text/xsl"'
rid='GUID0'
primary-weight='0.4' />
<new type='element'
ns='http://www.w3.org/1999/xhtml'
name='html'
rid='GUID1'
primary-weight='3' />
<new type='attr'
ns='xml'
name='lang'
chdata='fi'
parent='GUID1'
rid='GUID2' />
<set target='GUID2'
version='1'
chdata='en' />
<new type='element'
name='head'
parent='GUID1'
rid='GUID3' />
<new type='element'
name='title'
parent='GUID3'
rid='GUID4' />
<new type='text'
chdata='Royal Musings'
rid='GUID5'
parent='GUID4'
primary-weight='0'/>
<new type='comment'
chdata='The title of the document goes here.'
rid='GUID6'
parent='GUID4'
primary-weight='-2.43'/>
<new type='element'
name='body'
parent='GUID1'
rid='GUID7'
primary-weight='23' />
<document-end
last-sender='jid3'
last-id='abc'/>
</state>
</sxe>
</message>
]]></example>
</section2>
</section1>
<section1 topic='Subsequent State Changes'>
<p>Once a participant has received initial state, he can participate in the editing session.</p>
<example caption='An edit'><![CDATA[
<message
to='[email protected]/castle'
from='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='4'>
<state>
<new type='element'
name='p'
parent='GUID7'
rid='GUID8' />
<new type='text'
chdata='It's good to be the king!'
parent='GUID8'
rid='GUID9'/>
<set target='GUID5'
version='1'
chdata='It's good to be the king!'/>
</state>
</sxe>
</message>
]]></example>
<p>Here is another edit in the session.</p>
<example caption='Another edit'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='4'>
<state>
<new type='element'
name='p'
parent='GUID7'
rid='GUID10' />
<new type='text'
chdata='It certainly is!'
parent='GUID10'
rid='GUID11' />
<set target='GUID5'
version='1'
chdata='It certainly is' />
<set target='GUID6'
version='1'
replacefrom='9'
replacen='16'
chdata='' />
<set target='GUID6'
version='2'
replacefrom='3'
replacen='0'
chdata='document'/>
</state>
</sxe>
</message>
]]></example>
<p>This basic editing session results in the following XML.</p>
<example caption='Resulting XHTML document (with additional whitespace nodes for clarity)'><![CDATA[
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<?xml-stylesheet href="style.xsl" type="text/xsl"?>
<html>
<head>
<!--The document title goes here.-->
<title>Royal Musings</title>
</head>
<body>
<p>It's good to be the king!</p>
<p>It certainly is!</p>
</body>
</html>
]]></example>
</section1>
<section1 topic='Formal Definition' anchor='def'>
<section2 topic='SXE Element' anchor='def-sxe'>
<p>All SXE elements MUST be contained in a <sxe/> element. This element MUST posess the following attributes:</p>
<table caption="Attributes of <sxe/> element">
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
<tr>
<td>xmlns</td>
<td>REQUIRED and MUST be "urn:xmpp:sxe:0"</td>
</tr>
<tr>
<td>session</td>
<td>REQUIRED and MUST be a GUID of the session.</td>
</tr>
<tr>
<td>id</td>
<td>REQUIRED and MUST be unique within the set of <sxe/> elements sent by the user to the session.</td>
</tr>
</table>
</section2>
<section2 topic="XML Document Requirements">
<p>The prolog of the XML document cannot be edited after the session has been established.</p>
<p>If an XML Schema Definition is specified for the document and the processing of an <sxe/> element results in a noncompliant document, the receiving client SHOULD reply with edits that effectively undo the offending edits. TODO: the offending client should probably be notified.</p>
</section2>
<section2 topic="Mapping the Records to the DOM Document">
<p>A record contains the following fields and corresponds to a single DOM node:</p>
<table caption='The fields of a record'>
<tr>
<th>Field Name</th>
<th>Mutable</th>
<th>Applies to nodes of type</th>
<th>Description</th>
</tr>
<tr>
<td>rid</td>
<td>no</td>
<td>all</td>
<td>The GUID of the record.</td>
</tr>
<tr>
<td>type</td>
<td>no</td>
<td>all</td>
<td>The type of DOM node (element, attr, etc.).</td>
</tr>
<tr>
<td>version</td>
<td>Indirectly</td>
<td>all</td>
<td>The current version of the record.</td>
</tr>
<tr>
<td>parent</td>
<td>yes</td>
<td>all</td>
<td>The record id of the record corresponding to the parent node.</td>
</tr>
<tr>
<td>primary-weight</td>
<td>yes</td>
<td>all</td>
<td>The primary weight used to determine the order of sibling nodes corresponding to the records.</td>
</tr>
<tr>
<td>ns</td>
<td>yes (TODO: is this reasonable?)</td>
<td>element, attr</td>
<td>The namespace of the element or attribute</td>
</tr>
<tr>
<td>name</td>
<td>yes (TODO: is this reasonable?)</td>
<td>element, attr</td>
<td>The name of the element or attribute.</td>
</tr>
<tr>
<td>chdata</td>
<td>yes</td>
<td>text, attr, comment</td>
<td>The content of a text node or a comment or the value of the attribute.</td>
</tr>
<tr>
<td>pitarget</td>
<td>yes (TODO: is this reasonable?)</td>
<td>proccessinginstruction</td>
<td>The target of the processing instruction.</td>
</tr>
<tr>
<td>pidata</td>
<td>yes</td>
<td>proccessinginstruction</td>
<td>The data of the processing instruction.</td>
</tr>
</table>
<p>Whenever a record is added, modified, or removed, the client MUST ensure that the DOM nodes corresponding to the records meet the following criteria:</p>
<ol>
<li>The parent of each DOM node MUST be the node corresponding to the record specified by the 'record id' field of the record of the node. If no such record exists, the "orphan" record MUST be deleted. If the 'parent' field is empty, the node corresponding to the record MUST be a child of the DOM document itself. If two root nodes exist, the record with lower secondary weight MUST be removed. </li>
<li>Each node MUST be located after the child node that has the greatest weight less than the weight of the node.</li>
<li>The namespace of each DOM element and attribute MUST be equal to the 'name' field of the corresponding record.</li>
<li>The name of each DOM element and attribute MUST be equal to the 'name' field of the corresponding record. If two records for attribute nodes specify the same 'name' and 'parent', the record with lower secondary weight MUST be removed.</li>
<li>The value of each DOM attribute node MUST be equal to the 'chdata' field of the corresponding record.</li>
<li>The content of each DOM text node MUST be equal to the 'chdata' field of the corresponding record.</li>
<li>The content of each DOM comment node MUST be equal to the 'chdata' field of the corresponding record.</li>
<li>The target of each DOM processing instruction MUST be equal to the 'pitarget' field of the corresponding record.</li>
<li>The data of each DOM processing instruction MUST be equal to the 'pidata' field of the corresponding record.</li>
<li>The DOM nodes do not offend the XML Schema. If they do, the client SHOULD send edits to correct the situation.</li>
</ol>
<table caption='Example set of records'>
<tr>
<th>rid</th>
<th>type</th>
<th>version</th>
<th>parent</th>
<th>primary-weight</th>
<th>ns</th>
<th>name</th>
<th>chdata</th>
<th>pitarget</th>
<th>pidata</th>
</tr>
<tr>
<td>GUID0</td>
<td>element</td>
<td>0</td>
<td></td>
<td>0</td>
<td>http://www.w3.org/2000/svg</td>
<td>svg</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>GUID1</td>
<td>element</td>
<td>0</td>
<td>GUID0</td>
<td>0</td>
<td></td>
<td>path</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>GUID2</td>
<td>attr</td>
<td>0</td>
<td>GUID1</td>
<td>0</td>
<td></td>
<td>d</td>
<td>M10 10L20 20L20 10Z</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>GUID9</td>
<td>element</td>
<td>0</td>
<td>GUID0</td>
<td>3.4</td>
<td></td>
<td>g</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>GUID5</td>
<td>element</td>
<td>0</td>
<td>GUID0</td>
<td>3.4</td>
<td></td>
<td>circle</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>GUID6</td>
<td>attr</td>
<td>3</td>
<td>GUID5</td>
<td>0</td>
<td></td>
<td>cx</td>
<td>10</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>GUID7</td>
<td>attr</td>
<td>1</td>
<td>GUID5</td>
<td>1</td>
<td></td>
<td>cy</td>
<td>20</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>GUID8</td>
<td>attr</td>
<td>0</td>
<td>GUID5</td>
<td>2</td>
<td></td>
<td>r</td>
<td>5</td>
<td>N/A</td>
<td>N/A</td>
</tr>
</table>
<example caption='Corresponding XML document (without the XML prolog)'><![CDATA[
<svg xmlns='http://www.w3.org/2000/svg'>
<path d='M10 10L20 20L20 10Z' />
<circle cx='10' cy='20' r='5' />
<g />
</svg>
]]></example>
</section2>
<section2 topic='Commutative and Non-commutative Edits'>
<p>Changes to the records can be divided into two categories: commutative and non-commutative edits.</p>
<p>Commutative edits are commutative with all edits and are never "undone" so keeping a history of them is NOT REQUIRED. Edits that add or remove records are commutative.</p>
<p>An edit that changes an existing record is called non-commutative because it may not be commutative with edits that change the same record. Hence these changes may need to be undone so keeping a history of the changes caused by such edits is REQUIRED. The breadth of this required history depends on the role of the entity and on whether the session works through a server component:</p>
<table caption='Matrix of required history'>
<tr>
<td></td>
<th>By server</th>
<th>By client</th>
</tr>
<tr>
<th>Server exists</th>
<td>All non-commutative edits, that have not been undone to records that have not been removed; must store the creator and last modifier of each node (to be included as 'creator' and 'last-modified-by' attributes in <new/> elements sent to joining clients).</td>
<td>Non-commutative edits sent by the client itself. May be removed once a further non-commutative edits to the same record from another entity is received.</td>
</tr>
<tr>
<th>Server does not exists</th>
<td>---</td>
<td>All non-commutative edits, that have not been undone, to records that have not been removed.</td>
</tr>
</table>
<section3 topic='Requirements for the Server Component' anchor='serverrequirements'>
<p>The server MUST apply commutatative edits to its local copy like a client and pass on the edits without changes.</p>
<p>The server component intercepts and modifies non-commutative edits in order to reduce the history requirements of the clients as indicated above. Once it receives a non-commutative edit, it MUST take the following action depending on whether the version number of the edit is "in-order" (one higher than the current version) or "out-of-order":</p>
<ol>
<li>The server receives an in-order non-commutative edit: the server does not modify the edit, applies it locally, and passes it on normally.</li>
<li>The server receives an out-of-order non-commutative edit: it processes the edit like a client would in order to locally undo conflicting edits; then, instead of passing on the out-of-order edit, the server replaces the edit by an in-order non-commutative edit that results in a record identical to what the server has locally after the (possible) undos. Note that this edit may be a "no-op" that merely increases the version of the target.</li>
</ol>
</section3>
</section2>
<section2 topic='Commutative Edits' anchor='commutativeedits'>
<section3 topic='Creating New Nodes' anchor='newnode'>
<p>A client can add a new node to the document by adding a record with the <new/> element.</p>
<table caption="Attributes of the <new/> element">
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
<tr>
<td>rid</td>
<td>REQUIRED. MUST be a GUID.</td>
</tr>
<tr>
<td>version</td>
<td>OPTIONAL. MUST be a non-negative integer. Assumed to be 0 if not present.</td>
</tr>
<tr>
<td>parent</td>
<td>REQUIRED (Except at top level.)</td>
</tr>
<tr>
<td>primary-weight</td>
<td>OPTIONAL. MUST be a float. Assumed to be 0 if not present.</td>
</tr>
<tr>
<td>type</td>
<td>REQUIRED. MUST be 'element', 'attr', 'text', 'comment', or 'processinginstruction'</td>
</tr>
<tr>
<td>ns</td>
<td>OPTIONAL if 'type' is 'element' or 'attr'. Not allowed otherwise.</td>
</tr>
<tr>
<td>name</td>
<td>REQUIRED if 'type' is 'element' or 'attr'. Not allowed otherwise.</td>
</tr>
<tr>
<td>chdata</td>
<td>REQUIRED if 'type' is 'attr', 'text', or 'comment'. Not allowed otherwise.</td>
</tr>
<tr>
<td>pitarget</td>
<td>REQUIRED if 'type' is 'processinginstruction'. Not allowed otherwise.</td>
</tr>
<tr>
<td>pidata</td>
<td>REQUIRED if 'type' is 'processinginstruction'. Not allowed otherwise.</td>
</tr>
<tr>
<td>creator</td>
<td>OPTIONAL. MUST be the JID or room nick of the creator of the node.</td>
</tr>
<tr>
<td>last-modified-by</td>
<td>OPTIONAL. MUST be the JID or room nick of the user who last modified the node.</td>
</tr>
</table>
<example caption='Sending new nodes'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='11'>
<new type='element'
name='path'
parent='GUID1'
rid='GUID4' />
<new type='attr'
name='d'
parent='GUID4'
rid='GUID5'
chdata='M10 10L30 50L50 10Z' />
</sxe>
</message>
]]></example>
<p>To process a <new/> element the client MUST create a new record with the values of the attributes stored in the corresponding fields.</p>
</section3>
<section3 topic='Removing Nodes' anchor='editelement'>
<p>A client can remove any node in the document by removing the corresponding record with the <remove/> element.</p>
<table caption="Attributes of the <remove/> element">
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
<tr>
<td>target</td>
<td>REQUIRED and MUST be the record id of the node to be removed.</td>
</tr>
</table>
<p>A client MUST NOT send a <remove/> element that removes a node that has child nodes without explicitly removing the records of those nodes first.</p>
<example caption='Removing an existing nodes.'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='13'>
<remove target='GUID5'/>
<remove target='GUID4'/>
</sxe>
</message>
]]></example>
<p>To processes a <remove/> element the client MUST remove the record specified by the 'target' attribute.</p>
<p>If the node corresponding to the target record has child nodes, the receiver MUST send <remove/> elements for each of them as described above.</p>
</section3>
</section2>
<section2 topic='Non-commutative Edits' anchor='noncommutativeedits'>
<section3 topic='The set Element'>
<p>The <set/> element is used to modify an existing record.</p>
<table caption="Attributes of the <set/> element">
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
<tr>
<td>target</td>
<td>REQUIRED and MUST be the record id of the node being modified.</td>
</tr>
<tr>
<td>version</td>
<td>REQUIRED and MUST be the current version of the node incremented by one.</td>
</tr>
<tr>
<td>parent</td>
<td>OPTIONAL.</td>
</tr>
<tr>
<td>primary-weight</td>
<td>OPTIONAL.</td>
</tr>
<tr>
<td>ns</td>
<td>OPTIONAL but only allowed if the target record is of type 'element' or 'attr'.</td>
</tr>
<tr>
<td>name</td>
<td>OPTIONAL but only allowed if the target record is of type 'element' or 'attr'.</td>
</tr>
<tr>
<td>chdata</td>
<td>OPTIONAL but only allowed if the target node is of type 'attr', 'text', or 'comment'.</td>
</tr>
<tr>
<td>pitarget</td>
<td>OPTIONAL but only allowed if the target record is of type 'processinginstruction'.</td>
</tr>
<tr>
<td>pidata</td>
<td>OPTIONAL but only allowed if the target record is of type 'processinginstruction'.</td>
</tr>
<tr>
<td>replacefrom</td>
<td>replace from position. OPTIONAL but only allowed if 'chdata' and 'replacen' attributes are also included. MUST be a non-negative integer.</td>
</tr>
<tr>
<td>replacen</td>
<td>replace n characters. OPTIONAL but only allowed if 'chdata' and 'replacefrom' attributes are also included. MUST be a non-negative integer.</td>
</tr>
</table>
<example caption='set elements.'><![CDATA[
<message
from='[email protected]/castle'
to='[email protected]/castle'>
<sxe xmlns='urn:xmpp:sxe:0'
session='851ba2'
id='14'>
<set target='GUID14'
version='1'
chdata='10' />
<set target='GUID8'
version='1'
parent='GUID1'
primary-weight='8' />
</sxe>
</message>