git-svn-id: file:///home/ksmith/gitmigration/svn/xmpp/trunk@688 4b5297f7-1745-476d-ba37-a9c6900126ab
This commit is contained in:
Peter Saint-Andre 2007-03-23 22:07:22 +00:00
parent b72ed9cada
commit 5b60caa978
1 changed files with 159 additions and 118 deletions

View File

@ -6,8 +6,8 @@
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Jingle Audio Content Description Format</title>
<abstract>This document defines a content description format for Jingle audio sessions.</abstract>
<title>Jingle Audio via RTP</title>
<abstract>This document defines methods for negotiating Jingle audio sessions that use the Real-time Transport Protocol (RTP) for media exchange.</abstract>
&LEGALNOTICE;
<number>0167</number>
<status>Experimental</status>
@ -24,6 +24,13 @@
&scottlu;
&stpeter;
&seanegan;
&robmcqueen;
<revision>
<version>0.8</version>
<date>2007-03-23</date>
<initials>psa/ram</initials>
<remark><p>Renamed to mention RTP as the associated transport; corrected negotiation flow to be consistent with SIP/SDP (each party specifies a list of the payload types it can receive); added profile attribute to content element in order to specify RTP profile in use.</p></remark>
</revision>
<revision>
<version>0.7</version>
<date>2006-12-21</date>
@ -86,7 +93,7 @@
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>&xep0166; can be used to initiate and negotiate a wide range of peer-to-peer sessions. One session type of interest is audio (voice) chat. This document specifies a format for describing Jingle audio sessions.</p>
<p>&xep0166; can be used to initiate and negotiate a wide range of peer-to-peer sessions. One session type of interest is audio chat. This document specifies a format for describing Jingle audio sessions.</p>
</section1>
<section1 topic='Requirements' anchor='reqs'>
<p>The Jingle content description format defined herein is designed to meet the following requirements:</p>
@ -151,98 +158,111 @@
<payload-type id='13' name='CN'/>
</description>
]]></example>
<p>The &lt;description/&gt; element is intended to be a child of a &JINGLE; element as specified in <cite>XEP-0166</cite>. (See <link uurl='#ns'>Protocol Namespaces</link> regarding issuance of a permanent namespace.)</p>
<p>The &lt;description/&gt; element is intended to be a child of a &JINGLE; element as specified in <cite>XEP-0166</cite>.</p>
<p>Each &lt;payload-type/&gt; element MAY contain one or more child elements that specify particular parameters related to the payload. For example, as described in <cite>draft-ietf-avt-rtp-speex</cite> <note>This Internet-Draft has expired; see &lt;<link url='http://www.watersprings.org/pub/id/draft-ietf-avt-rtp-speex-00.txt'>http://www.watersprings.org/pub/id/draft-ietf-avt-rtp-speex-00.txt</link>&gt; for an archived version.</note>, the "ebw", "eng", "mode", "sr", and "vbr" parameters may be specified in relation to usage of the Speex <note>See &lt;<link url='http://www.speex.org/'>http://www.speex.org/</link>&gt;.</note> codec. Where such parameters are encoded via the "fmtp" SDP attribute, they shall be represented in Jingle via the following format:</p>
<code><![CDATA[
<parameter name='foo' value='bar'/>
]]></code>
<p>Note: The parameter names are effectively guaranteed to be unique, since &IANA; maintains a registry of SDP parameters (see &lt;<link url='http://www.iana.org/assignments/sdp-parameters'>http://www.iana.org/assignments/sdp-parameters</link>&gt;).</p>
</section1>
<section1 topic='Negotiating a Jingle-Audio Session' anchor='negotiating'>
<p>Upon receiving a Jingle initiate stanza containing a Jingle Audio content description as defined in this document, a target entity iterates through the list of offered payload types, composing an appropriate Jingle Audio response description according to the following rules:</p>
<ul>
<li>If the target entity does not support the offered encoding, it MUST NOT include the encoding in its response.</li>
<li>If the target entity does support the offered encoding, it SHOULD include encoding in the response, preseriving the offered payload type.</li>
<li>If the target entity is unable to support the offered encoding with the offered payload type, it MAY provide an alternate payload type in its response. This typically will happen only when translating from other signalling protocols.</li>
<li>The target entity SHOULD preserve the order of the offered encodings, which represents the priority assigned to them by the initator.</li>
</ul>
<p>If, after applying these rules, the target entity determines it does not support any of the offering encodings, the target entity MUST reject the session by sending a &lt;unsupported-codecs/&gt; error in response to the initiator's "initiate" message. Otherwise, it MUST provisionally accept the session by sending an empty IQ result. If the response content type differs from the one offered, the target entity MUST then propose the change in a "description-modify" message as defined in <cite>XEP-0166</cite>. If the description is identical, the target entity MUST send a "description-accept" message (either explictly, or implicitly as part of a "content-accept" message).</p>
<p>Following is an example of this negotiation:</p>
<section1 topic='Negotiating a Jingle Audio Session' anchor='negotiation'>
<p>When the initiator sends a session-initiate stanza to the receiver, the &DESCRIPTION; element includes all of the payload types that the initiator can receive for Jingle audio (each one encapsulated in a separate &PAYLOADTYPE; element):</p>
<example caption="Initiation Example"><![CDATA[
<iq to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard' id='jingleaudio1' type='set'>
<jingle xmlns='http://jabber.org/protocol/jingle'
action='session-initiate'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content name='audio'>
<description xmlns='http://jabber.org/protocol/jingle/description/audio'>
<payload-type id='96' name='speex' clockrate='16000'/>
<payload-type id='0' name='PCMU' />
</description>
<transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>
...
</transport>
</content>
</jingle>
</iq>
]]></example>
<p>The target entity now follows the rules provided in this section and determines it can only support PCMU. It provisionally accepts the session:</p>
<example caption="Target Provisionally Accepts Session"><![CDATA[
<iq to='romeo@montague.net/orchard' from='juliet@capulet.com/balcony' id='jingleaudio1' type='result' />
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='jingleaudio1' type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'>
action='session-initiate'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content name='this-is-the-audio-content' profile='RTP/AVP'>
<description xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns'>
<payload-type id='96' name='speex' clockrate='16000'/>
<payload-type id='97' name='speex' clockrate='8000'/>
<payload-type id='18' name='G729'/>
<payload-type id='103' name='L16' clockrate='16000' channels='2'/>
<payload-type id='98' name='x-ISAC' clockrate='8000'/>
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0176.html#ns'/>
</content>
</jingle>
</iq>
]]></example>
<p>It then offers the new content description in a 'description-modify' message:</p>
<example caption="Initiation Example"><![CDATA[
<iq to='romeo@montague.net/orchard' from='juliet@capulet.com/balcony' id='jingleaudio2' type='set'>
<jingle xmlns='http://jabber.org/protocol/jingle'
action='description-modify'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content name='audio'>
<description xmlns='http://jabber.org/protocol/jingle/description/audio'>
<payload-type id='0' name='PCMU' />
</description>
</content>
</jingle>
</iq>
]]></example>
<p>The initiator acknowledges the 'description-modify' with an empty IQ result, and sends a 'description-accept' to accept
the new Jingle Audio content description.</p>
<example caption="Initiator Accepts New Content Description"><![CDATA[
<iq to='juliet@capulet.com/balcony' from='romeo@montegue.net/orchard' id='jingleaudio2' type='result' />
<iq to='juliet@capulet.com/balcony' from='romeo@montegue.net/orchard' id='jingleaudio3' type='set' />
<jingle xmlns='http://jabber.org/protocol/jingle'
action='description-accept' initiator='romeo@montague.net/orchard' sid='a73sjjvkla37jfea'>
<content name='audio'>
<description xmlns='http://jabber.org/protocol/jingle/description/audio'>
<payload-type id='0' name='PCMU' />
</description>
</content>
</jingle>
</iq>
<p>Upon receiving the session-initiate stanza, the receiver determines whether it can provisionally accept the session and proceed with the negotiation. The general Jingle error cases are specified in <cite>XEP-0166</cite>. In addition, the receiver must determine if it supports any of the payload types advertised by the initiator; if it does not, it MUST reject the session by sending a &lt;unsupported-codecs/&gt; error:</p>
<example caption="Receiver Does Not Support Codecs"><![CDATA[
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingleaudio1'>
<error type='cancel'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported-codecs xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns-errors'/>
</error>
</iq>
]]></example>
<p>Finally, the target acknowledges the 'description-accept'.</p>
<example caption="Target Provisionally Accepts Session"><![CDATA[
<iq to='romeo@montague.net/orchard' from='juliet@capulet.com/balcony' id='jingleaudio3' type='result' />
<p>If there is no error, the receiver provisionally accepts the session:</p>
<example caption="Receiver Provisionally Accepts Session"><![CDATA[
<iq from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingleaudio1' type='result' />
]]></example>
<p>The receiver then should send a list of the payload types that it can receive via a Jingle "content-accept" (or "session-accept") action. The list that the receiver sends MAY include any payload types (not a subset of the payload types sent by the initiator) but SHOULD retain the ID numbers and order specified by the initiator.</p>
<example caption="Receiver Accepts Content Type"><![CDATA[
<iq from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingleaudio2' type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'>
action='content-accept'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content name='this-is-the-audio-content' profile='RTP/AVP'>
<description xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns'>
<payload-type id='97' name='speex' clockrate='8000'/>
<payload-type id='18' name='G729'/>
<payload-type id='0' name='PCMU' />
<payload-type id='102' name='iLBC'/>
<payload-type id='4' name='G723'/>
<payload-type id='8' name='PCMA'/>
<payload-type id='13' name='CN'/>
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0176.html#ns'/>
</content>
</jingle>
</iq>
]]></example>
<p>The initiator acknowledges the 'content-accept' with an empty IQ result:</p>
<example caption="Initiator Acknowledges Modified Content Description"><![CDATA[
<iq from='romeo@montegue.net/orchard' to='juliet@capulet.com/balcony' id='jingleaudio2' type='result' />
]]></example>
<p>After successful transport negotiation (not shown here), the receiver then accepts the session:</p>
<example caption="Receiver Definitively Accepts the Session"><![CDATA[
<iq type='set' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='accept1'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='session-accept'
initiator='romeo@montague.net/orchard'
responder='juliet@capulet.com/balcony'
sid='a73sjjvkla37jfea'>
<content creator='initiator' name='this-is-the-audio-content' profile='RTP/AVP'>
<description xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns'/>
<transport xmlns='http://www.xmpp.org/extensions/xep-0176.html#ns'>
<candidate component='2'
foundation='1'
generation='0'
ip='192.0.2.3'
network='1'
port='45664'
priority='1107821052'
protocol='udp'
pwd='asd88fgpdd777uzjYhagZg'
type='srflx'
ufrag='8hhy'/>
</transport>
</content>
</jingle>
</iq>
]]></example>
<p>And the initiator acknowledges session acceptance:</p>
<example caption="Initiator Acknowledges Session Acceptance"><![CDATA[
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='accept1' type='result' />
]]></example>
</section1>
<section1 topic='Mapping to Session Description Protocol' anchor='sdp'>
<p>If the payload type is static (payload-type IDs 0 through 95 inclusive), it MUST be mapped to a media field defined in <cite>RFC 4566: Session Description Protocol</cite> (SDP). The generic format for the media field is as follows:</p>
<p>If the payload type is static (payload-type IDs 0 through 95 inclusive), it MUST be mapped to a media field defined in <cite>RFC 4566</cite>. The generic format for the media field is as follows:</p>
<code><![CDATA[
m=<media> <port> <transport> <fmt list>
]]></code>
<p>In the context of Jingle audio sessions, the &lt;content&gt; is "audio", the &lt;port&gt; is the preferred port for such communications (which may be determined dynamically), the &lt;transport&gt; is whatever transport method is negotiated via the Jingle negotiation (e.g., "RTP/AVT"), and the &lt;fmt list&gt; is the payload-type ID.</p>
<p>In the context of Jingle audio sessions, the &lt;media&gt; is "audio", the &lt;port&gt; is the preferred port for such communications (which may be determined dynamically), the &lt;transport&gt; is whatever transport method is negotiated via the Jingle negotiation (e.g., "RTP/AVT"), and the &lt;fmt list&gt; is the payload-type ID.</p>
<p>For example, consider the following static payload-type:</p>
<example caption="Jingle Format for Static Payload-Type"><![CDATA[
<payload-type id="13" name="CN"/>
@ -251,7 +271,7 @@ m=<media> <port> <transport> <fmt list>
m=audio 9999 RTP/AVP 13
]]></example>
<p>If the payload type is dynamic (payload-type IDs 96 through 127 inclusive), it SHOULD be mapped to an SDP media field plus an SDP attribute field named "rtpmap".</p>
<p>For example, consider a payload of 16-bit linear-encoded stereo audio sampled at 16KHz associated with dynamic payload-type 98:</p>
<p>For example, consider a payload of 16-bit linear-encoded stereo audio sampled at 16KHz associated with dynamic payload-type 96:</p>
<example caption="Jingle Format for Dynamic Payload-Type"><![CDATA[
<payload-type id='96' name='speex' clockrate='16000'/>
]]></example>
@ -259,7 +279,7 @@ m=audio 9999 RTP/AVP 13
m=audio 9999 RTP/AVP 96
a=rtpmap:96 speex/16000
]]></example>
<p>As noted, if additional parameters are to be specified, they shall be represented as attributes of the &lt;payload-type/&gt; element or of the child &lt;parameter/&gt; element, as in the following example.</p>
<p>As noted, if additional parameters are to be specified, they shall be represented as attributes of the &lt;payload-type/&gt; element of the child &lt;parameter/&gt; element, as in the following example.</p>
<example caption="Jingle Format for Dynamic Payload-Type With Parameters"><![CDATA[
<payload-type id='96' name='speex' clockrate='16000' ptime='40'>
<parameter name='vbr' value='on'/>
@ -273,33 +293,9 @@ a=ptime:40
a=fmtp:96 vbr=on;cng=on
]]></example>
</section1>
<section1 topic='Service Discovery' anchor='disco'>
<p>If an entity supports the Jingle audio content description format, it MUST advertise that fact by returning a feature of "http://www.xmpp.org/extensions/xep-0167.html#ns" (see <link url='#ns'>Protocol Namespaces</link>) in response to &xep0030; information requests.</p>
<example caption="Service Discovery Information Request"><![CDATA[
<iq from='romeo@montague.net/orchard'
id='disco1'
to='juliet@capulet.com/balcony'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<example caption="Service Discovery Information Response"><![CDATA[
<iq from='juliet@capulet.com/balcony'
id='disco1'
to='romeo@montague.net/orchard'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='http://www.xmpp.org/extensions/xep-0166.html#ns'/>
<feature var='http://www.xmpp.org/extensions/xep-0167.html#ns'/>
...
</query>
</iq>
]]></example>
</section1>
<section1 topic='Informational Messages' anchor='info'>
<section2 topic='Format' anchor='info-format'>
<p>Informational messages may be sent by either party within the context of Jingle to communicate the status of a Jingle audio session, device, or principal. The informational message MUST be an IQ-set containing a &JINGLE; element of type "description-info", where the informational message is a payload element qualified by the 'http://www.xmpp.org/extensions/xep-0167.html#ns-info' namespace; the following payload elements are defined: <note>A &lt;trying/&gt; element (equivalent to the SIP 100 Trying response code) is not necessary, since each session-level action is acknowledged via XMPP IQ semantics.</note></p>
<p>Informational messages may be sent by either party within the context of Jingle to communicate the status of a Jingle audio session, device, or principal. The informational message MUST be an IQ-set containing a &JINGLE; element of type "session-info", where the informational message is a payload element qualified by the 'http://www.xmpp.org/extensions/xep-0167.html#ns-info' namespace; the following payload elements are defined: <note>A &lt;trying/&gt; element (equivalent to the SIP 100 Trying response code) is not necessary, since each session-level action is acknowledged via XMPP IQ semantics.</note></p>
<table caption='Information Payload Elements'>
<tr>
<th>Element</th>
@ -330,8 +326,8 @@ a=fmtp:96 vbr=on;cng=on
to='romeo@montague.net/orchard'
id='busy1'
type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='description-info'
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'>
action='session-info'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<busy xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns-info'/>
@ -344,7 +340,7 @@ a=fmtp:96 vbr=on;cng=on
id='hold1'
type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='description-info'
action='session-info'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<hold xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns-info'/>
@ -357,7 +353,7 @@ a=fmtp:96 vbr=on;cng=on
id='mute1'
type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='description-info'
action='session-info'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<mute xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns-info'/>
@ -370,7 +366,7 @@ a=fmtp:96 vbr=on;cng=on
id='ringing1'
type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='description-info'
action='session-info'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<ringing xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns-info'/>
@ -381,7 +377,7 @@ a=fmtp:96 vbr=on;cng=on
</section1>
<section1 topic='Error Handling' anchor='errors'>
The Jingle Audio-specific error conditions are as follows:
<p>The Jingle Audio-specific error conditions are as follows:</p>
<table caption='Other Error Conditions'>
<tr>
<th>Jingle Condition</th>
@ -394,7 +390,31 @@ The Jingle Audio-specific error conditions are as follows:
<td>The recipient does not support any of the offered audio encodings.</td>
</tr>
</table>
</section1>
<section1 topic='Determining Support' anchor='support'>
<p>If an entity supports Jingle audio exchanges via RTP, it MUST advertise that fact by returning a feature of "http://www.xmpp.org/extensions/xep-0167.html#ns" &NSNOTE; in response to &xep0030; information requests.</p>
<example caption="Service Discovery Information Request"><![CDATA[
<iq from='romeo@montague.net/orchard'
id='disco1'
to='juliet@capulet.com/balcony'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<example caption="Service Discovery Information Response"><![CDATA[
<iq from='juliet@capulet.com/balcony'
id='disco1'
to='romeo@montague.net/orchard'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='http://www.xmpp.org/extensions/xep-0166.html#ns'/>
<feature var='http://www.xmpp.org/extensions/xep-0167.html#ns'/>
...
</query>
</iq>
]]></example>
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
@ -405,12 +425,12 @@ The Jingle Audio-specific error conditions are as follows:
<p>If it is necessary to send Dual Tone Multi-Frequency (DTMF) tones, it is REQUIRED to use the XML format specified &xep0181;.</p>
</section2>
<section2 topic='When to Listen' anchor='impl-listen'>
<p>When the Jingle Audio content is accepted, either by a 'content-accept' action or a combination of 'description-accept' and 'transport-accept' actions, both receiving and sending entities SHOULD start listening for audio as defined by the negotiated transport method and audio description. For interoperability with telephony systems, each entity SHOULD both play any audio received and send a ringing tone, at this time, before the receiver sends a 'session-accept' action.</p>
<p>When the Jingle Audio content is accepted via a 'content-accept' action, both initiator and responder SHOULD start listening for audio as defined by the negotiated transport method and audio description. For interoperability with telephony systems, each entity SHOULD both play any audio received and send a ringing tone at this time (i.e., before the receiver sends a 'session-accept' action).</p>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>The description of a format for audio sessions introduces no known security vulnerabilities.</p>
<p>In order to secure the data stream, implementations SHOULD use encryption methods appropriate to the transport method and media being exchanged; for example, in the case of UDP, that would include Datagram Transport Layer Security (DTLS) as specified in &rfc4347;. &sdpdtls; defines such methods for the Session Description Protocol; the relevant RTP profile (e.g., "UDP/TLS/RTP/AVP" for transporting the RTP stream over DTLS with UDP) shall be specified as the value of the &CONTENT; element's 'profile' attribute.</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
@ -422,11 +442,11 @@ The Jingle Audio-specific error conditions are as follows:
<p>Until this specification advances to a status of Draft, its associated namespaces shall be "http://www.xmpp.org/extensions/xep-0167.html#ns" and "http://www.xmpp.org/extensions/xep-0167.html#ns-info"; upon advancement of this specification, the &REGISTRAR; shall issue permanent namespaces in accordance with the process defined in Section 4 of &xep0053;.</p>
</section2>
<section2 topic='Jingle Content Description Formats' anchor='registrar-content'>
<p>The XMPP Registrar shall include "audio" in its registry of Jingle content description formats. The registry submission is as follows:</p>
<p>The XMPP Registrar shall include "audio-rtp" in its registry of Jingle content description formats. The registry submission is as follows:</p>
<code><![CDATA[
<content>
<name>audio</name>
<desc>Jingle sessions that support audio exchanges</desc>
<name>audio-rtp</name>
<desc>Jingle sessions that support audio exchange via the Real-time Transport Protocol</desc>
<doc>XEP-0167</doc>
</content>
]]></code>
@ -483,6 +503,27 @@ The Jingle Audio-specific error conditions are as follows:
</xs:restriction>
</xs:simpleType>
</xs:schema>
]]></code>
</section2>
<section2 topic='Errors' anchor='schema-errors'>
<code><![CDATA[
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='http://www.xmpp.org/extensions/xep-0167.html#ns-errors'
xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns-errors'
elementFormDefault='qualified'>
<xs:element name='unsupported-codecs' type='empty'/>
<xs:simpleType name='empty'>
<xs:restriction base='xs:string'>
<xs:enumeration value=''/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
]]></code>
</section2>