Expressions are used in import rules and style sheets.

Use in style sheets

They are used in <if> and <condition> elements. You write them using the exp attribute. For example:

<if exp='scale > 50000'>
<condition exp='$="Italy"'>

You can use the special variables $, Type, OsmType and RoadType in style sheet expressions. $ is the name, Type is the integer type, OsmType is the same as (Type bitand #FFFE0000), and RoadType is the same as (Type bitand #FC0). For example,

<condition exp='OsmType == "cit"'>

is clearer and easier to write than the equivalent

<condition exp='(Type bitand #FFFE0000) == "cit"'>

Road types can be written using special string literal values. They are matched on the first five characters of the road type name, plus a suffix of 'link' to indicate a link road, or a digit suffix to indicate a road of type other0...other7.

The road type names are motorway, trunk, primary, secondary, tertiary, unclassified, residential, track, service, pedestrian, vehicular ferry, passenger ferry, other0, ..., other7.

Therefore acceptable values include:
"motorway link"
"trunk road"
"other road type 0"
Here is a style sheet condition to select trunk roads:

<condition exp='RoadType=="trunk"'/>

Use in import rules

They are used in the test or else attribute of any statement.


Expressions support most C++, Java or JavaScript operators, but there are some extensions and differences:

  • You can use and, or, bitand, bitor, le, lt, eq, gt and ge instead of &&, ||, &, |, <=, <, ==, > and >=. This is especially useful where XML makes it hard to use & and <, for which you have to substitute & and <. The operator = means the same as ==.
  • There are special equality operators to ignore case (eqc), ignore case and accents (eqa), use fuzzy matching (eqf), and use wild cards (eqw).
  • The operators in and notin work with sets and ranges. A set is a comma-separated list enclosed in { }, and a range is a comma-separated pair of items enclosed in [ ], giving inclusive lower and upper bounds. The in and notin operators have the same precedence as comparison operators..
  • There is a string concatenation operator written as two full stops: ..
  • As in JavaScript, strings are automatically converted to numeric values where needed. Thus, 3 == '3' is true, and so is 256 == '0x100'. We extend that by converting 3-letter strings to type codes used in CartoType, as in (Type bitand 0xFFFE0000) == 'cit'. When two strings are compared, however, they don't need to be converted, and the comparison is lexicographic.
  • Identifiers are attribute names. The identifier Type, in style sheet expressions, refers to the integer attribute. Other identifiers refer to string attributes.
  • In style sheets the special identifier @ refers to the object type: 0=point, 1=line, 2=polygon, 3=array (e.g., terrain). So you can write a <condition> to select polygon objects only: <condition exp="@=2">.
  • In import rules @node means 'in a node', @way means 'in a way', @relation means 'in a relation'; and @ is undefined
  • Strings can be delimited using ' or ". Inside a string delimited with ', the escape sequences \' and \\ can be used for ' and \. Inside a string delimited with " the escape sequences \" and \\ can be used for " and \. There are no other escape sequences. You cannot use ' for ', because it is converted to ' by the XML parser before it gets to CartoType's expression parser. Obviously, if you delimit the entire expression with double quotes, you have to use single quotes for strings inside the expression, and vice versa.

Here are the operators in order of evaluation:

( ) - brackets enclosing a sub-expression

unary operators: + (unary plus), - (unary minus), ~ (bitwise not), and ! (logical not)

multiplicative operators: * (multiply), / (divide), % (modulo)

additive operators: + (plus), - (minus), .. (string concatenation)

shift operators: << (left shift), >> (right shift)

comparison operators: lt or < (less), le or <= (less or equal), eq or = or == (equal), neq or != (not equal), ge or >= (greater or equal), gt or > (greater), eqc (equal, ignoring case), eqa (equal, ignoring accents and case), eqf (equal using fuzzy matching), eqw (equal using wild cards)

range and set operators (same priority as comparison operators): in { a, b, ... } (in a set), notin { a, b, ... } (not in a set), in [ low, high ] (in a range), notin [ low, high ] (not in a range)

bitwise operators: bitand or & (bitwise and), bitor or | (bitwise or), xor or ^ (bitwise exclusive or)

logical operators: and or && (and), or or || (or)

Undefined variables

Comparisons for greater, less, greater than or equal, and less than or equal always return false for undefined variables. Therfore tests like 'population gt 0' or 'population le 250', both of which are used in the standard OSM import rules, return true only when attribute 'population' exists in a map object.

Comparisons for equality are subtle, but do what is usually expected. If var is undefined, 'var==0' returns false, but 'var==""' returns true. Thus the empty string is treated as the same as 'undefined', while 0, or any other number, is not the same as 'undefined'.

Logical tests

Logical tests, also called boolean or true-false tests, work like this: the value true is returned for all strings except the empty string, and for all numbers except 0. Undefined variables have the logical value 'false'. That allows you to test for the existence of an OSM attribute in import rules, or a map object string attribute in a style sheet, using an expression consisting of the variable name only, like 'var'.