RELAX NG by Eric van der Vlist will be published by O'Reilly & Associates (ISBN: 0596004214)

You are welcome to use our annotation system to give your feedback.


More Atoms

Atoms that exactly match a character are the simplest atoms that can be used in a pattern facet. The other atoms that can be used in pattern facets are special characters, a wildcard that matches any character, or predefined and user-defined character classes.

W3C XML Schema has adopted the "classical" Perl and Unicode character classes (but not the POSIX-style character classes also available in Perl), and user-defined classes are also available.

W3C XML Schema supports the classical Perl character classes plus a couple of additions to match XML-specific productions. Each of these classes are designated by a single letter; the classes designated by the upper- and lowercase versions of the same letter are complementary:

These character classes may be used with an optional quantifier like any other atom. The last pattern facet that we saw:

multipleOfTen = xsd:integer {pattern = ".*0"}

constrains the lexical space to be a string of characters ending with a zero. Knowing that the base type is an xsd:integer, is good enough for our purposes, but if the base type had been an xsd:decimal (or xsd:string), we could be more restrictive and write:

multipleOfTen = xsd:integer {pattern = "-?\d*0"}

This checks that the characters before the trailing zero are digits with an optional leading - (we will see later on in Section 6.5.2.2 how to specify an optional leading - or +).

Patterns support character classes matching both Unicode categories and blocks. Categories and blocks are two complementary classification systems: categories classify the characters by their usage independently of their localization (letters, uppercase, digit, punctuation, etc.), while blocks classify characters by their localization independently of their usage (Latin, Arabic, Hebrew, Tibetan, and even Gothic or musical symbols).

The syntax \p{Name} is similar for blocks and categories; the prefix Is is added to the name of categories to make the distinction. The syntax \P{Name} is also available to select the characters that do not match a block or category. A list of Unicode blocks and categories is given in the specification. Table 6-2 shows the Unicode character classes and Table 6-3 shows the Unicode character blocks.

We will see in the next section that W3C XML Schema has introduced an extension to Regular Expressions to specify intersections, This extension can be used to define the intersection between a block and a category in a single pattern facet.

[Note]Note

Although Unicode blocks seem to be a great way to restrict text to a set of characters which you know that you'll be able to print, display, read or store in a database, they have not been designed for this purpose and one must be careful when using them for this purpose. John Cowan, who has taught courses on Unicode and enjoys obscure alphabets, wrote about this topic:

It's important to note that Unicode blocks are a very crude mechanism for discrimination: not everything needed to write Greek is in the Greek block, and there are no less than five Latin blocks, one of which (Basic Latin, i.e. ASCII) contains many script-independent symbols. The blocks were originally created solely for internal Unicode organizational purposes, and have spread to the outside world somewhat randomly.

The five Latin blocks mentioned by John are BasicLatin, Latin-1Supplement, LatinExtended-A, LatinExtendedAdditional and LatinExtended-B.

These classes are lists of characters between square brackets that accept - signs to define ranges and a leading ^ to negate the whole list--for instance:

[azertyuiop]

to define the list of letters on the first row of a French keyboard,

[a-z]

to specify all the characters between "a" and "z",

[^a-z]

for all the characters that are not between "a" and "z," but also

[-^\\]

to define the characters "-," "^," and "\," or

[-+]

to specify a decimal sign.

These examples demonstrate that the contents of these square brackets follows a specific syntax and semantic. Like the regular expression's main syntax, we have a list of atoms, but instead of matching each atom against a character of the instance string, we define a logical space. Brackets operate in a space between the atoms and more formal character classes.

We see also two special characters that have a different meaning depending on their location. The character -, which is a range delimiter when it is between a and z, is a normal character when it is just after the opening bracket or just before the closing bracket ([+-] and [-+] are, therefore, both legal). On the contrary, ^, which is a negator when it appears at the beginning of a class, loses this special meaning to become a normal character later in the class definition.

[Note]Note

Even though this is specified as valid by the W3C XML Schema recommendation, it is not supported by all the regular expression engines used by RELAX NG processors. The current version of the Jing parser (as I write these lines) supports neither [+-] nor [-+] and it is wiser to escape the character - and write either [+\-] or [\-+].

Another frequent source of confusion is about the support of the escape format #xXX (such as in #x2D. Because this format is used in the W3C XML Schema recommendation to describe characters by their Unicode value, some people have thought that it could be used in regular expressions, but this is not meant to be used that way. If you want to define characters by their Unicode values, you should use numeric entities instead (such as - if you are using the XML syntax or the syntax for escaping characters in the compact syntax \x{2D}). Note that in both cases, the reference will be replaced by the corresponding character at parse time and that the regular expression engine will see the actual character instead of the escape sequence.

Also, some characters may or must be escaped: "\\" is used to match the character "\". In fact, in a class definition, all the escape sequences that we have seen as atoms can be used. Even though some of the special characters lose their special meaning inside square brackets, they can always be escaped. So, the following:

[\-^\\]

can also be written as:

[\-\^\\]

or as:

[\^\\\-]

since the location of the characters doesn't matter any longer when they are escaped.

Within square brackets, the character "\" also keeps its meaning of a reference to a Perl or Unicode class. The following:

[\d\p{Lu}]

is a set of decimal digits (Perl class \d) and uppercase letters (Unicode category "Lu").

Mathematicians have found that three basic operations are needed to manipulate sets and that these operations can be chosen from a larger set of operations. In our square brackets, we've already seen two of these operations: union (the square bracket is an implicit union of its atoms) and complement (a leading ^ realizes the complement of the set defined in the square bracket). W3C XML Schema extends the syntax of Perl regular expressions to introduce a third operation: the difference between sets. The syntax follows:

[set1-[set2]]

Its meaning is that all the characters in set1 that do not belong to set2, where set1 and set2 can use all the syntactic tricks that we have seen up to now.

This operator can be used to perform intersections of character classes (the intersection between two sets A and B is the difference between A and the complement of B), and we can now define a class for the BasicLatin Letters as:

[\p{IsBasicLatin}-[^\p{L}]]

Or, using the \P construct, which is also a complement, we can define the class as:

[\p{IsBasicLatin}-[\P{L}]]

The corresponding definition would be:

  <define name="BasicLatinLetters">
    <data type="token">
      <param name="pattern">[\p{IsBasicLatin}-[\P{L}]]*</param>
    </data>
  </define>

Or:

 BasicLatinLetters = xsd:token {pattern = "[\p{IsBasicLatin}-[\P{L}]]*"}

You are welcome to use our annotation system to give your feedback.
[Annotations for this page]
All text is copyright Eric van der Vlist, Dyomedea. During development, I give permission for non-commercial copying for educational and review purposes. After publication, all text will be released under the Free Software Foundation GFDL.