Copyright � The Organization for the Advancement of Structured Information Standards [OASIS] 2002. All Rights Reserved.
This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
This document specifies a compact, non-XML syntax for [RELAX NG].
This is a working draft constructed by the editor. It is not an official committee work product and may not reflect the consensus opinion of the committee. Comments on this document may be sent to relax-ng-comment@lists.oasis-open.org.
This specification describes a compact, non-XML syntax for [RELAX NG].
The goals of this syntax are:
The syntax has similarities to [XQuery Formal Semantics], to [XDuce] and to the DTD syntax of [XML 1.0].
The body of this document contains an informal description of the syntax and how it maps onto the XML syntax. Developers should consult Appendix A. Formal description for a complete, rigorous description.
The following is a summary of the syntax in EBNF. The reader may find it helpful to compare this with the syntax in Section 3 of [RELAX NG]. The start symbol is topLevel.
topLevel | ��::=�� | decl* (pattern | grammarContent*) |
decl | ��::=�� | "namespace " identifierOrKeyword "= " namespaceUri| " default " "namespace " [identifierOrKeyword] "= " namespaceUri| " datatypes " identifierOrKeyword "= " literal |
pattern | ��::=�� | "element " nameClass "{ " pattern "} "| " attribute " nameClass "{ " pattern "} "| pattern (" , " pattern)+| pattern (" & " pattern)+| pattern (" | " pattern)+| pattern " ? "| pattern " * "| pattern " + "| " list " "{ " pattern "} "| " mixed " "{ " pattern "} "| identifier | " parent " identifier| " empty "| " text "| [datatypeName] datatypeValue | datatypeName [" { " param* "} "] [exceptPattern]| " notAllowed "| " externalRef " uri [inherit]| " grammar " "{ " grammarContent* "} "| " ( " pattern ") " |
param | ��::=�� | identifierOrKeyword "= " literal |
exceptPattern | ��::=�� | "- " pattern |
grammarContent | ��::=�� | start | define | " div " "{ " grammarContent* "} "| " include " uri [inherit] ["{ " includeContent* "} "] |
includeContent | ��::=�� | define | start | " div " "{ " includeContent* "} " |
start | ��::=�� | "start " assignMethod pattern |
define | ��::=�� | identifier assignMethod pattern |
assignMethod | ��::=�� | "= "| " |= "| " &= " |
nameClass | ��::=�� | name | nsName [exceptNameClass] | anyName [exceptNameClass] | nameClass " | " nameClass| " ( " nameClass ") " |
name | ��::=�� | identifierOrKeyword | CName |
exceptNameClass | ��::=�� | "- " nameClass |
datatypeName | ��::=�� | CName | " string "| " token " |
datatypeValue | ��::=�� | literal |
uri | ��::=�� | literal |
namespaceUri | ��::=�� | literal | " inherit " |
inherit | ��::=�� | "inherit " "= " identifierOrKeyword |
identifierOrKeyword | ��::=�� | identifier | keyword |
identifier | ��::=�� | (NCName - keyword) | quotedIdentifier |
quotedIdentifier | ��::=�� | "\ " NCName |
CName | ��::=�� | NCName ": " NCName |
nsName | ��::=�� | NCName ":* " |
anyName | ��::=�� | "* " |
literal | ��::=�� | literalSegment+ |
literalSegment | ��::=�� | '" ' (Char - '" ')* '" '| " ' " (Char - "' ")* "' " |
keyword | ��::=�� | "attribute "| " default "| " datatypes "| " div "| " element "| " empty "| " externalRef "| " grammar "| " include "| " inherit "| " list "| " mixed "| " namespace "| " notAllowed "| " parent "| " start "| " string "| " text "| " token " |
NCName is defined in [XML Namespaces]. Char is defined in [XML 1.0].
In order to use a keyword as an identifier, it must be quoted with \. It is not necessary to quote a keyword that is used as the name of an element or attribute or as datatype parameter.
The value of a literal is the concatenation of the values of its constituent literalSegments. The value of a literal segment consists of the characters between the opening and closing quote. The way to get a literal whose value contains both a single and a double quote is to divide the literal into multiple literalSegments so that the single and double quote are in separate literalSegments.
Annotations can be specified as described in Section 5.
There is no notion of operator precedence. It is an error for patterns to combine the |, &, , and - operators without using parentheses to make the grouping explicit. For example, foo | bar, baz is not allowed; instead, either (foo | bar), baz or foo | (bar, baz) must be used. A similar restriction applies to name classes and the use of the | and - operators. These restrictions are not expressed in the above EBNF but they are made explicit in the BNF in Section A.1.
Whitespace is allowed between tokens. Tokens are the quoted terminals appearing in the EBNF in Section 2, except that literalSegment, nsName, CName, identifier and quotedIdentifer are single tokens.
Comments are also allowed between tokens. Comments start with a # and continue to the end of the line. Comments starting with ## are treated specially; see Section 5.
A Unicode character with hex code N can be represented by the escape sequence \x{N}. Using such an escape sequence is completely equivalent to the entering the corresponding character directly. For example,
element \x{66}\x{6f}\x{6f} { empty }
is equivalent to
element foo { empty }
A datatypes declaration declares a prefix used in a QName identifying a datatype. For example,
datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes" element height { xsd:double }
In fact, in the above example, the datatypes declaration is not required: the xsd prefix is predeclared to the above URI.
A namespace declaration declares a prefix used in a QName specifying the name of an element or attribute. For example,
namespace rng = "http://relaxng.org/ns/structure/1.0" element rng:text { empty }
As in XML, the xml prefix is predeclared.
A default namespace declaration declares the namespace used for unprefixed names specifying the name of an element (but not of an attribute). For example,
default namespace = "http://example.com" element foo { attribute bar { string } }
is equivalent to
namespace ex = "http://example.com" element ex:foo { attribute bar { string } }
A default namespace declaration may have a prefix as well. For example,
default namespace ex = "http://example.com"
is equivalent to
default namespace = "http://example.com" namespace ex = "http://example.com"
The URI may be empty. This makes the prefix stand for the absent namespace URI. This is necessary for specifying a name class that matches any name with an absent namespace URI. For example:
namespace local = "" element foo { attribute * - local:* { string }* }
is equivalent to
<element xmlns="http://relaxng.org/ns/structure/1.0"" name="foo" ns="http://example.com"> <zeroOrMore> <attribute> <anyName> <except> <nsName ns=""/> </except> </anyName> <data type="string"/> </attribute> <zeroOrMore> </element>
RELAX NG has the feature that if a file does not specify an ns attribute then the ns attribute can be inherited from the including file. To support this feature, the keyword inherit can be specified in place of the namespace URI in a namespace declaration. For example,
default namespace this = inherit element foo { element * - this:* { string }* }
is equivalent to
<element xmlns="http://relaxng.org/ns/structure/1.0"" name="foo"> <zeroOrMore> <element> <anyName> <except> <nsName/> </except> </anyName> <data type="string"/> </element> <zeroOrMore> </element>
In addition, the include and externalRef patterns can specify inherit = prefix to specify the namespace to be inherited by the referenced file. For example,
namespace x = "http://www.example.com" externalRef "foo.rng" inherit = x
is equivalent to
<externalRef href="foo.rng" ns="http://www.example.com" xmlns="http://relaxng.org/ns/structure/1.0"/>
In the absence of an inherit parameter on include or externalRef, the default namespace will be inherited by the referenced file.
In the absence of a default namespace declaration, a declaration of
default namespace = inherit
is assumed.
An annotation in square brackets can be inserted immediately before a pattern, nameClass, grammarContent or includeContent. It has the following syntax:
annotation | ��::=�� | "[ " annotationAttribute* annotationElement* "] " |
annotationAttribute | ��::=�� | name "= " literal |
annotationElement | ��::=�� | name "[ " annotationAttribute* (annotationElement | literal)* "] " |
Each of the annotationAttributes will turn into attributes on the corresponding RELAX NG element. Each of the annotationElements will turn into initial children of the corresponding RELAX NG element, except in the case where the RELAX NG element cannot have children, in which case they will turn into following elements.
Comments starting with ## are used to specify documentation elements from the http://relaxng.org/ns/compatibility/annotations/1.0 namespace as described in [Compatibility]. For example,
## Represents a language element lang { ## English "en" | ## Japanese "jp" }
turns into
<element name="lang" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0"> <a:documentation>Represents a language</a:documentation> <choice> <value>en</value> <a:documentation>English</a:documentation> <value>jp</value> <a:documentation>Japanese</a:documentation> </choice> </element>
## comments can only be used immediately before before a pattern, nameClass, grammarContent or includeContent. Multiple ## comments are allowed. Multiple adjacent ## comments without any intervening blank lines are merged into a single documentation element. Any ## comments must precede any annotation in square brackets.
A pattern or nameClass may be followed by any number of followAnnotations with the following syntax:
followAnnotation | ��::=�� | ">> " annotationElement |
Each such annotationElement turns into an following sibling of the RELAX NG element representing the pattern or nameClass.
An annotationElement may be used in any place where grammarContent or includeContent is allowed. For example,
namespace x = "http://www.example.com" start = foo x:notation [ name="jpeg" systemId="http://www.example.com/jpeg" ] foo = element foo { empty }
turns into
<grammar xmlns:x="http://www.example.com" xmlns="http://relaxng.org/ns/structure/1.0"> <start> <ref name="foo"/> </start> <x:notation name="jpeg" systemId="http://www.example.com/jpeg"/> <define name="foo"> <element name="foo"> <empty/> </element> </define> </grammar>
If the name of such an element is a keyword, then it must be escaped.
The compact syntax is specified by a grammar in BNF. The translation into the XML syntax is specified by annotations in the grammar.
The start symbol is topLevel.
The BNF description consists of a set of production rules. Each production rule has a left-hand side and right-hand side separated by ::=. The left-hand side specifies the name of a non-terminal. The right-hand side specifies a list of one or more alternatives separated by |. Each alternative consists of a sequence of terminals and non-terminals. A non-terminal is specified by a name in italics. A terminal is either a literal string in quotes or a named non-terminal specified by a name in bold italics. An alternative can also be specified as ε, which denotes an empty sequence of tokens.
Each alternative may be followed by references to one or more named constraints that apply to that alternative.
The translation into XML syntax is specified by associating a value with each terminal and non-terminal in the derivation. Each alternative in the BNF may be followed by an expression in curly braces, which specifies how to compute the value associated with the left-hand side non-terminal. Each terminal and non-terminal on the right-hand side can be labelled with a subscript specifying a variable name. When that variable name is used within the curly braces, it refers to the value associated with that terminal or non-terminal. If an alternative consists of a single terminal or non-terminal, then the expression in curly braces can be omitted; in this case the value of the left-hand side is the value of that terminal or non-terminal.
The result of the translation is not a string containing the XML representation of a RELAX NG schema, but rather is an instance of the data model described in Section 2 of [RELAX NG]; this instance will match the RELAX NG schema for RELAX NG.
The computation of the value of a non-terminal may make use of one or more arguments. The name of such a non-terminal is always followed by a list of arguments. When the name of the non-terminal occurs on the left-hand-side, this list declares the formal arguments for the non-terminal. When the name occurs on the right-hand side of a producton, the list specifies the actual arguments which will be bound to the formal arguments during the computation of the value of the non-terminal. The expressions in curly braces on the right-hand side can refer to the formal arguments declared on the left-hand side. For example, see simpleNameClass.
In addition to explicit arguments, every non-terminal implicitly has an argument that specifies a context for the interpretation of a pattern. Normally the implicit context argument to each non-terminal is the same as its parent; an expression followed by a period followed by a non-terminal references that non-terminal with the context argument changed to be the value of that expression. For example, see topLevel and preamble. In the initial context used for the start symbol, xml is bound as a namespace prefix to http://www.w3.org/XML/1998/namespace, and xsd is bound as a datatype prefix to http://www.w3.org/2001/XMLSchema-datatypes.
Expressions use the following notation:
xyzzy
" denotes a string
consisting of the characters
xyzzy;<group
>
y </group>
) unless
x is equal to emptyAnnotations(), in which case it is equivalent to y;<choice
>
y </choice>
) unless
x is equal to emptyAnnotations(), in which case it is equivalent to y;<foo
x>
y </foo>
denotes
an element from the RELAX NG namespace with local name
foo, attributes x and content
x.topLevel��::=
����preamblec��c.topLevelBodyx
��������{ x }
preamble��::=
����ε
��������{ context }
����|��declc��c.preambled
��������{ d }
decl��::=
����"namespace
"��namespacePrefixx��"=
"��namespaceUriy
��������Constraint: xml prefix
��������Constraint: xml namespace URI
��������Constraint: duplicate declaration
��������{ bindPrefix(context, x, y) }
����|��"default
"��"namespace
"��"=
"��namespaceUrix
��������Constraint: xml namespace URI
��������Constraint: duplicate declaration
��������{ bindDefault(context, x) }
����|��"default
"��"namespace
"��namespacePrefixx��"=
"��namespaceUriy
��������Constraint: xml prefix
��������Constraint: xml namespace URI
��������Constraint: duplicate declaration
��������{ bindDefault(bindPrefix(context, x, y), y) }
����|��"datatypes
"��datatypePrefixx��"=
"��literaly
��������Constraint: xsd prefix
��������Constraint: datatypes URI
��������Constraint: duplicate declaration
��������{ bindDatatypePrefix(context, x, y) }
namespacePrefix��::=
����identifierOrKeyword
��������Constraint: valid prefix
datatypePrefix��::=
����identifierOrKeyword
namespaceUri��::=
����literal
����|��"inherit
"
��������{ inherit }
topLevelBody��::=
����pattern
����|��grammarx
��������{ <grammar
>
x </grammar>
}
grammar��::=
����ε
��������{ ( ) }
����|��memberx��grammary
��������{ (x, y) }
member��::=
����annotatedComponent
����|��annotationElementNotKeyword
annotatedComponent��::=
����annotationsx��componenty
��������{ applyAnnotations(x, y) }
component��::=
����start
����|��define
����|��include
����|��div
start��::=
����"start
"��assignOpx��patterny
��������{ <start
x>
y </start>
}
define��::=
����identifierx��assignOpy��patternz
��������{ <define
name=
x
y>
z </define>
}
assignOp��::=
����"=
"
��������{ { } }
����|��"|=
"
��������{ attribute(name("", "
combine
"), "choice
") }
����|��"&=
"
��������{ attribute(name("", "
combine
"), "interleave
") }
include��::=
����"include
"��literalx��optInherity��optIncludeBodyz
��������{ <include
href=
mapSchemaRef(x)
y>
z </include>
}
optInherit��::=
����ε
��������{ makeNsAttribute(lookupDefault(context)) }
����|��"inherit
"��"=
"��identifierOrKeywordx
��������{ makeNsAttribute(lookupPrefix(context, x)) }
optIncludeBody��::=
����ε
��������{ ( ) }
����|��"{
"��includeBodyx��"}
"
��������{ x }
includeBody��::=
����ε
��������{ ( ) }
����|��includeMemberx��includeBodyy
��������{ (x, y) }
includeMember��::=
����annotatedIncludeComponent
����|��annotationElementNotKeyword
annotatedIncludeComponent��::=
����annotationsx��includeComponenty
��������{ applyAnnotations(x, y) }
includeComponent��::=
����start
����|��define
����|��includeDiv
div��::=
����"div
"��"{
"��grammarx��"}
"
��������{ <div
>
x </div>
}
includeDiv��::=
����"div
"��"{
"��includeBodyx��"}
"
��������{ <div
>
x </div>
}
pattern��::=
����innerPattern(emptyAnnotations())
innerPattern(anno)��::=
����innerParticle(anno)
����|��particleChoicex
��������{ applyAnnotations(anno, <choice
>
x </choice>
) }
����|��particleGroupx
��������{ applyAnnotations(anno, <group
>
x </group>
) }
����|��particleInterleavex
��������{ applyAnnotations(anno, <interleave
>
x </interleave>
) }
����|��annotatedDataExceptx
��������{ applyAnnotationsGroup(anno, x) }
particleChoice��::=
����particlex��"|
"��particley
��������{ (x, y) }
����|��particlex��"|
"��particleChoicey
��������{ (x, y) }
particleGroup��::=
����particlex��",
"��particley
��������{ (x, y) }
����|��particlex��",
"��particleGroupy
��������{ (x, y) }
particleInterleave��::=
����particlex��"&
"��particley
��������{ (x, y) }
����|��particlex��"&
"��particleInterleavey
��������{ (x, y) }
particle��::=
����innerParticle(emptyAnnotations())
innerParticle(anno)��::=
����annotatedPrimaryx
��������{ applyAnnotationsGroup(anno, x) }
����|��repeatedPrimaryx��followAnnotationsy
��������{ (applyAnnotations(anno, x), y) }
repeatedPrimary��::=
����annotatedPrimaryx��"*
"
��������{ <zeroOrMore
>
x </zeroOrMore>
}
����|��annotatedPrimaryx��"+
"
��������{ <oneOrMore
>
x </oneOrMore>
}
����|��annotatedPrimaryx��"?
"
��������{ <optional
>
x </optional>
}
annotatedPrimary��::=
����leadAnnotatedPrimaryx��followAnnotationsy
��������{ (x, y) }
annotatedDataExcept��::=
����leadAnnotatedDataExceptx��followAnnotationsy
��������{ (x, y) }
leadAnnotatedDataExcept��::=
����annotationsx��dataExcepty
��������{ applyAnnotations(x, y) }
leadAnnotatedPrimary��::=
����annotationsx��primaryy
��������{ applyAnnotations(x, y) }
����|��annotationsx��"(
"��innerPattern(x)y��")
"
��������{ y }
primary��::=
����"element
"��nameClass(true)x��"{
"��patterny��"}
"
��������{ <element
>
x y </element>
}
����|��"attribute
"��nameClass(false)x��"{
"��patterny��"}
"
��������{ <attribute
>
x y </attribute>
}
����|��"mixed
"��"{
"��patternx��"}
"
��������{ <mixed
>
x </mixed>
}
����|��"list
"��"{
"��patternx��"}
"
��������{ <list
>
x </list>
}
����|��datatypeNamex��optParamsy
��������{ <data
x>
y </data>
}
����|��datatypeNamex��datatypeValuey
��������{ <value
x>
y </value>
}
����|��datatypeValuex
��������{ <value
>
x </value>
}
����|��"empty
"
��������{ <empty
/>
}
����|��"notAllowed
"
��������{ <notAllowed
/>
}
����|��"empty
"
��������{ <text
/>
}
����|��refx
��������{ <ref
name=
x/>
}
����|��"parent
"��refx
��������{ <parentRef
name=
x/>
}
����|��"grammar
"��"{
"��grammarx��"}
"
��������{ <grammar
>
x </grammar>
}
����|��"externalRef
"��literalx��optInherity
��������{ <externalRef
href=
mapSchemaRef(x)
y/>
}
dataExcept��::=
����datatypeNamex��optParamsy��"-
"��leadAnnotatedPrimaryz
��������{ <data
x>
y <except
>
z </except>
</data>
}
ref��::=
����identifier
datatypeName��::=
����CNamex
��������{ datatypeAttributes(lookupDatatypePrefix(context, prefix(x)), localPart(x)) }
����|��"string
"
��������{ datatypeAttributes("", "
string
") }
����|��"token
"
��������{ datatypeAttributes("", "
token
") }
datatypeValue��::=
����literal
optParams��::=
����ε
��������{ ( ) }
����|��"{
"��paramsx��"}
"
��������{ x }
params��::=
����ε
��������{ ( ) }
����|��paramx��paramsy
��������{ (x, y) }
param��::=
����annotationsx��identifierOrKeywordy��"=
"��literalz
��������{ applyAnnotations(x, <param
name=
y>
z </param>
) }
nameClass(elem)��::=
����innerNameClass(elem, emptyAnnotations())
innerNameClass(elem, anno)��::=
����annotatedSimpleNameClass(elem)x
��������{ applyAnnotationsChoice(anno, x) }
����|��nameClassChoice(elem)x
��������{ applyAnnotations(anno, <choice
>
x </choice>
) }
����|��annotatedExceptNameClass(elem)x
��������{ applyAnnotationsChoice(anno, x) }
nameClassChoice(elem)��::=
����annotatedSimpleNameClass(elem)x��"|
"��annotatedSimpleNameClass(elem)y
��������{ (x, y) }
����|��annotatedSimpleNameClass(elem)x��"|
"��nameClassChoice(elem)y
��������{ (x, y) }
annotatedExceptNameClass(elem)��::=
����leadAnnotatedExceptNameClass(elem)x��followAnnotations(elem)y
��������{ (x, y) }
leadAnnotatedExceptNameClass(elem)��::=
����annotations(elem)x��exceptNameClass(elem)y
��������{ applyAnnotations(x, y) }
annotatedSimpleNameClass(elem)��::=
����leadAnnotatedSimpleNameClass(elem)x��followAnnotations(elem)y
��������{ (x, y) }
leadAnnotatedSimpleNameClass(elem)��::=
����annotationsx��simpleNameClass(elem)y
��������{ applyAnnotations(x, y) }
����|��annotationsx��"(
"��innerNameClass(elem, x)y��")
"
��������{ y }
exceptNameClass(elem)��::=
����nsNamex��"-
"��leadAnnotatedSimpleNameClass(elem)y
��������Constraint: name class except
��������{ <nsName
makeNsAttribute(lookupPrefix(context, x))>
<except
>
y </except>
</nsName>
}
����|��"*
"��"-
"��leadAnnotatedSimpleNameClass(elem)x
��������Constraint: name class except
��������{ <anyName
>
<except
>
x </except>
</anyName>
}
simpleNameClass(elem)��::=
����identifierOrKeywordx
��������{ <name
makeNsAttribute(elem ? lookupDefault(context) : "")
>
x </name>
}
����|��CNamex
��������{ <name
makeNsAttribute(lookupPrefix(context, prefix(x)))>
localPart(x) </name>
}
����|��nsNamex
��������{ <nsName
makeNsAttribute(lookupPrefix(context, x))/>
}
����|��"*
"
��������{ <anyName
/>
}
followAnnotations��::=
����ε
��������{ ( ) }
����|��">>
"��annotationElementx��followAnnotationsy
��������{ (x, y) }
annotations��::=
����documentationsx
��������{ pair({ }, x) }
����|��documentationsx��"[
"��prefixedAnnotationAttributesy��annotationElementsz��"]
"
��������{ pair(y, (x, z)) }
prefixedAnnotationAttributes��::=
����ε
��������{ ( ) }
����|��prefixedAnnotationAttributex��prefixedAnnotationAttributesy
��������Constraint: duplicate attributes
��������Constraint: unqualified name
��������{ (x, y) }
annotationElements��::=
����ε
��������{ ( ) }
����|��annotationElementx��annotationElementsy
��������{ (x, y) }
annotationElement��::=
����identifierOrKeywordx��"[
"��annotationAttributesy��annotationContentz��"]
"
��������{ element(name("", x), y, z) }
����|��colonAnnotationElement
annotationElementNotKeyword��::=
����identifierx��"[
"��annotationAttributesy��annotationContentz��"]
"
��������{ element(name("", x), y, z) }
����|��colonAnnotationElement
colonAnnotationElement��::=
����prefixedNamex��"[
"��annotationAttributesy��annotationContentz��"]
"
��������{ element(x, y, z) }
annotationContent��::=
����ε
��������{ ( ) }
����|��annotationElementx��annotationContenty
��������{ (x, y) }
����|��literalx��annotationContenty
��������{ (x, y) }
annotationAttributes��::=
����ε
��������{ ( ) }
����|��annotationAttributex��annotationAttributesy
��������Constraint: duplicate attributes
��������{ (x, y) }
annotationAttribute��::=
����prefixedAnnotationAttribute
����|��unprefixedAnnotationAttribute
prefixedAnnotationAttribute��::=
����prefixedNamex��"=
"��literaly
��������Constraint: xmlns namespace URI
��������{ attribute(x, y) }
prefixedName��::=
����CNamex
��������Constraint: annotation inherit
��������{ name(lookupPrefix(context, prefix(x)), localPart(x)) }
unprefixedAnnotationAttribute��::=
����identifierOrKeywordx��"=
"��literaly
��������{ attribute(name("", x), y) }
documentations��::=
����ε
��������{ ( ) }
����|��documentationx��documentationsy
��������{ (element(documentationElementName(), { }, x), y) }
identifierOrKeyword��::=
����identifier
����|��keyword
keyword��::=
����"attribute
"
����|��"default
"
����|��"datatypes
"
����|��"div
"
����|��"element
"
����|��"empty
"
����|��"externalRef
"
����|��"grammar
"
����|��"include
"
����|��"inherit
"
����|��"list
"
����|��"mixed
"
����|��"namespace
"
����|��"notAllowed
"
����|��"parent
"
����|��"start
"
����|��"string
"
����|��"text
"
����|��"token
"
It is an error if the value of a namespacePrefix is xmlns.
It is an error if the value of namespacePrefix is xml and the the value of the namespaceUri is not http://www.w3.org/XML/1998/namespace.
It is an error if the value of the namespaceUri is http://www.w3.org/XML/1998/namespace and the value of the namespacePrefix is not xml.
It is an error if the value of datatypePrefix is xsd and the the value of the literal is not http://www.w3.org/2001/XMLSchema-datatypes.
It is an error if the value of the literal in a datatypes declaration is not a syntactically legal value for a datatypeLibrary as specified in Section 3 of [RELAX NG].
It is an error if there is more than one namespace declaration of a particular prefix, more than one default namespace declaration or more than one declaration of a particular datatypes prefix.
It is an error if the value of exceptNameClass is such that it violates the constraint in the second paragraph of Section 4.16 of [RELAX NG]: "An except element that is a child of an anyName element must not have any anyName descendant elements. An except element that is a child of an nsName element must not have any nsName or anyName descendant elements."
It is an error if the namespace URI of a prefixedName in a prefixedAnnotationAttributes is the empty string.
It is an error if the namespace URI of a prefixedName in a prefixedAnnotationAttribute is http://www.w3.org/2000/xmlns.
It is an error if a prefixedAnnotationAttributes or an annotationAttributes contains two attributes with the same namespace URI and local name.
It is an error if the namespace URI in the value of a prefixedName is inherit.
This section describes how to transform the textual representation of a RELAX NG schema in compact syntax into a sequence of tokens, which can be parsed using the grammar specified in Section A.1.
There are six distinct stages, which are logically consecutive; the result of each stage is the input to the following stage.
The textual representation of the RELAX NG schema in compact syntax may be either a sequence of Unicode characters or a sequence of bytes. In the latter case, the first stage is to transform the sequence of bytes to the sequence of characters. The sequence of bytes may have associated metadata specifying the encoding. One example of such metadata is the charset parameter in a MIME media type. If there is such metadata, then the specified encoding is used. Otherwise, the first two bytes of the sequence are examined. If these are #xFF followed by #xFE or #xFE followed by #xFF, then an encoding of UTF-16 [Unicode] will be used, little-endian in the former case, big-endian in the latter case. Otherwise an encoding of UTF-8 [Unicode] is used. It is an error if the sequence of bytes is not a legal sequence in the selected encoding.
Representations of newlines are normalized to #xA in a similar way to [XML 1.0]. Specifically, each occurrence of a #xD character that is not followed by a #xA character or of a #xD, #xA character pair is transformed to #xA.
In this stage, each escape sequence of the form \x{n}, where n is a hexadecimal number, is replaced by the character with Unicode code n. The escape sequence must match the production escapeSequence; the value computed in the BNF is the Unicode code of the replacement character. It is an error if the replacement character does not match the Char production of [XML 1.0]. It is an error if the input character sequence contains a character sequence escapeOpen that does not start an escapeSequence. After an escape sequence has been replaced, scanning for escape sequences continues following the replacement character; thus \x{5C}x{5C} is transformed to \x{5C} not to \.
The \ character that opens an escape sequence may be followed by more than one x. This makes it possible for there to be a reversible transformation that maps a schema to a form containing only ASCII characters; the transformation replaces adds an extra x to each existing escape sequence, and replaces every non-ASCII character by an escape sequence with exactly one x.
escapeSequence��::=
����escapeOpen��hexNumberx��escapeClose
��������{ x }
escapeOpen��::=
����"\
"��xs��"{
"
escapeClose��::=
����"}
"
hexNumber��::=
����hexDigit
����|��hexNumberx��hexDigity
��������{ (x * 16) + y }
hexDigit��::=
����"0
"
��������{ 0 }
����|��"1
"
��������{ 1 }
����|��"2
"
��������{ 2 }
����|��"3
"
��������{ 3 }
����|��"4
"
��������{ 4 }
����|��"5
"
��������{ 5 }
����|��"6
"
��������{ 6 }
����|��"7
"
��������{ 7 }
����|��"8
"
��������{ 8 }
����|��"9
"
��������{ 9 }
����|��[A
a
]
��������{ 10 }
����|��[B
b
]
��������{ 11 }
����|��[C
c
]
��������{ 12 }
����|��[D
d
]
��������{ 13 }
����|��[E
e
]
��������{ 14 }
����|��[F
f
]
��������{ 15 }
In this stage, the sequence of characters is tokenized: it is transformed into a sequence of tokens, where each token corresponds to a non-terminal in the grammar in Section A.1, except that the token sequence contains literalSegment tokens instead of literal tokens.
A sequence of characters is tokenized by first finding the longest initial subsequence that:
If the longest such initial subsequence matches separator, this subsequence is discarded. Otherwise, a single non-terminal is produced from this initial subsequence. In either case, the tokenization proceeds with the rest of the character sequence. It is an error if there is no such initial subsequence.
The production rules below use some additional notation. Square brackets enclose a character class. A character class of the form [^chars] specifies any legal XML character that does not occur in chars. A legal XML character is a character that matches the Char production of [XML 1.0]. A character class of the form [chars], where chars does not being with ^, specifies any single character that occurs in chars. XML hexadecimal character references are used to denote a single character, as in XML. NCName is defined in [XML Namespaces].
identifier��::=
����NCNamex - keyword
��������{ x }
����|��"\
"��NCNamex
��������{ x }
CName��::=
����NCNamex��":
"��NCNamey
��������{ qName(x, y) }
nsName��::=
����NCNamex��":*
"
��������{ x }
literalSegment��::=
����""
"��stringNoQuotx��""
"
��������{ x }
����|��"'
"��stringNoAposx��"'
"
��������{ x }
stringNoQuot��::=
����ε
��������{ "" }
����|��[^"
]x��stringNoQuoty
��������{ stringConcat(x, y) }
stringNoApos��::=
����ε
��������{ "" }
����|��[^'
]x��stringNoAposy
��������{ stringConcat(x, y) }
documentation��::=
����documentationLine
����|��documentationx��documentationContinuationy
��������{ stringConcat(x, y) }
documentationLine��::=
����"##
"��restOfLinex
��������{ stripFirstSpace(x) }
documentationContinuation��::=
����[
]x��indent��documentationLiney
��������{ stringConcat(x, y) }
indent��::=
����ε
��������{ "" }
����|��[	 ]x��indenty
��������{ stringConcat(x, y) }
restOfLine��::=
����ε
��������{ "" }
����|��[^
]x��restOfLiney
��������{ stringConcat(x, y) }
separator��::=
����[	

 ]
����|��"#
"��[^
#
]��restOfLine
����|��"#
"
In this stage, each maximal sequence of consecutive literalSegment tokens is concatenated into a literal token.
literal��::=
����literalSegment
����|��literalSegmentx��literaly
��������{ stringConcat(x, y) }
# RELAX NG XML syntax specified in compact syntax. default namespace rng = "http://relaxng.org/ns/structure/1.0" namespace local = "" datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes" start = pattern pattern = element element { (nameQName | nameClass), (common & pattern+) } | element attribute { (nameQName | nameClass), (common & pattern?) } | element group|interleave|choice|optional |zeroOrMore|oneOrMore|list|mixed { common & pattern+ } | element ref|parentRef { nameNCName, common } | element empty|notAllowed|text { common } | element data { type, param*, (common & exceptPattern?) } | element value { commonAttributes, type?, xsd:string } | element externalRef { href, common } | element grammar { common & grammarContent* } param = element param { commonAttributes, nameNCName, xsd:string } exceptPattern = element except { common & pattern+ } grammarContent = definition | element div { common & grammarContent* } | element include { href, (common & includeContent*) } includeContent = definition | element div { common & includeContent* } definition = element start { combine?, (common & pattern+) } | element define { nameNCName, combine?, (common & pattern+) } combine = attribute combine { "choice" | "interleave" } nameClass = element name { commonAttributes, xsd:QName } | element anyName { common & exceptNameClass? } | element nsName { common & exceptNameClass? } | element choice { common & nameClass+ } exceptNameClass = element except { common & nameClass+ } nameQName = attribute name { xsd:QName } nameNCName = attribute name { xsd:NCName } href = attribute href { xsd:anyURI } type = attribute type { xsd:NCName } common = commonAttributes, foreignElement* commonAttributes = attribute ns { xsd:string }?, attribute datatypeLibrary { xsd:anyURI }?, foreignAttribute* foreignElement = element * - rng:* { (anyAttribute | text | anyElement)* } foreignAttribute = attribute * - (rng:*|local:*) { text } anyElement = element * { (anyAttribute | text | anyElement)* } anyAttribute = attribute * { text }