YSLD¶
The gt-ysld module provides a YAML parser/encoder for GeoTools style objects:
- human readable alternative to machine readable XML 
- compact representation 
- flexible syntax using indentation, rather than order 
- YAML parser provides variables for snippet reuse 
- Full access to GeoTools rendering engine not limited by SLD specification 
References:
- YSLD (GeoServer User Guide) 
- gt-main style layer descriptor (interfaces) 
- gt-api symbology encoding (interfaces) 
- style (tutorial) 
- gt-render style (code examples) 
YSLD Syntax¶
Quick example (the FeatureTypeStyle, Rule and list of Symbolizers is auto-generated):
line:
  stroke-color: '#3333cc'
Rules example (the FeatureTypeStyle is auto-generated):
rules:
- filter: ${type = 'road'}
  symbolizers:
  - line:
      stroke-color: '#000000'
      stroke-width: 2
- else: true
  symbolizers:
  - line:
      stroke-color: '#666666'
      stroke-width: 1
Complete example with names, titles and comments:
# Created on 2016-03-4
name: water
title: Lakes and Rivers
abstract: Water style using transparency to allow for hill
          shade bathymetry effects.
feature-styles:
- rules:
  - name: hydro
    title: Hydro
    symbolizers:
    - polygon:
        stroke-color: '#333089'
        stroke-width: 1.25
        fill-color: '#333089'
        fill-opacity: 0.45
Yet another markup language (YAML) uses indentation to form a document structure of mappings and lists. The specification supports comments, multiline text and definition reuse.
Expressions¶
Expressions are specified as CQL/ECQL parse-able expression strings. See the CQL documentation and this CQL tutorial for more information about the CQL syntax.
Literal examples:
line:
  stroke-width: 10
  stroke-linecap: 'butt'
Note: Single quotes are needed for string literals to differentiate them from attribute references.
Attribute example:
text:
  label: ${STATE_NAME}
Function example:
point:
  rotation: ${sqrt([STATE_POP])}
Color examples:
polygon:
  stroke-color: '#ff00ff'
  fill-color: rgb(255,0,255)
Color literals can be specified either as a 6 digit hex string or a 3 argument
rgb  function call.
Filters¶
Rule filters are specified as CQL/ECQL parse-able filters. A simple example:
rules:
- filter: ${type = 'highway'}
  symbolizers:
  - line:
      stroke-width: 5
See the CQL documentation and this CQL tutorial for more information about the CQL syntax.
Tuples¶
Some attributes are specified as pairs. For example:
rules:
- scale: [10000,20000]
point:
  anchor: [0.5,0.5]
The literal strings min and max can also be used:
rules:
- scale: [min,10000]
  symbolizers:
  - line:
    stroke-width: 3
- scale: [10000,max]
  symbolizers:
  - line:
    stroke-width: 1
Arrays¶
Lists and arrays are specified as space delimited. For example:
stroke-dasharray: '5 2 1 2'
Anchors & References¶
With YAML it is possible to reference other parts of a document. With this it is possible to support variables and mix ins. An example of a color variable:
redish: &redish '#DD0000'
point:
  fill-color: *redish
An named “anchor” is declared with the & character and then referenced with the * character. This same feature can be used to do “mix-ins” as well:
define: &highway_zoom10
  scale: (10000,20000)
  filter: type = 'highway'
rules:
- <<: *highway_zoom10
  symbolizers:
  - point
The syntax in this case is slightly different and is used when referencing an entire mapping object rather than just a simple scalar value.
YSLD Grammar¶
Document structure:
<YAML variable definition>
<grid definition>
<style definition>
Grid definition (predefined WGS84, WebMercator):
# grid definition
grid:
  name: <text>
Style definition:
# style definition
name: <text>
title: <text>
abstract: <text>
feature-styles:
- <feature style>
Optional top-level sld and layer definition:
# sld definition
sld-name: <text>
sld-title: <text>
sld-abstract: <text>
# named layer definition
layer-name: <text>
# user layer definition
user-name: <text>
user-remote: <text>
user-service: <text>
Feature style definition:
feature-styles:
- name: <text>
  title: <text>
  abstract: <text>
  transform:
    <transform>
  rules:
  - <rules>
  x-firstMatch: <boolean>
  x-composite: <text>
  x-composite-base: <boolean>
Rule definition:
# rules
rules:
- name: <text>
  title: <text>
  filter: <filter>
  else: <boolean>
  scale: [<min>,<max>]
  zoom: [<min>,<max>]
  symbolizers:
  - <symbolizers>
  x-inclusion: <text>
Line symbolizer definition:
symbolizers:
- line:
    geometry: <expression>
    uom: <text>
    x-labelObstacle: <boolean>
    x-composite-base: <boolean>
    x-composite: <text>
    stroke-color: <color>
    stroke-width: <expression>
    stroke-opacity: <expression>
    stroke-linejoin: <expression>
    stroke-linecap: <expression>
    stroke-dasharray: <float list>
    stroke-dashoffset: <expression>
    stroke-graphic:
      <graphic_options>
    stroke-graphic-fill:
      <graphic_options>
    offset: <expression>
Polygon symbolizer definition:
symbolizers:
- polygon:
    geometry: <expression>
    uom: <text>
    x-labelObstacle: <boolean>
    x-composite-base: <boolean>
    x-composite: <text>
    fill-color: <color>
    fill-opacity: <expression>
    fill-graphic:
      <graphic_options>
    stroke-color: <color>
    stroke-width: <expression>
    stroke-opacity: <expression>
    stroke-linejoin: <expression>
    stroke-linecap: <expression>
    stroke-dasharray: <float list>
    stroke-dashoffset: <expression>
    stroke-graphic:
      <graphic_options>
    stroke-graphic-fill:
      <graphic_options>
    offset: <expression>
    displacement: <expression>
Point symbolizer definition:
symbolizers:
- point:
    geometry: <expression>
    uom: <text>
    x-labelObstacle: <boolean>
    x-composite-base: <boolean>
    x-composite: <text>
    symbols:
    - external:
        url: <text>
        format: <text>
    - mark:
        shape: <shape>
        fill-color: <color>
        fill-opacity: <expression>
        fill-graphic:
          <graphic_options>
        stroke-color: <color>
        stroke-width: <expression>
        stroke-opacity: <expression>
        stroke-linejoin: <expression>
        stroke-linecap: <expression>
        stroke-dasharray: <float list>
        stroke-dashoffset: <expression>
        stroke-graphic:
          <graphic_options>
        stroke-graphic-fill:
          <graphic_options>
    size: <expression>
    rotation: <expression>
    anchor: <tuple>
    displacement: <tuple>
    opacity: <expression>
Raster symbolizer definition:
symbolizers:
- raster:
    opacity: <expression>
    channels:
      gray:
        <channel_options>
      red:
        <channel_options>
      green:
        <channel_options>
      blue:
        <channel_options>
    color-map:
      type: <ramp|interval|values>
      entries:
      - [color, entry_opacity, band_value, text_label]
    contrast-enhancement:
      mode: <normalize|histogram>
      gamma: <expression>
Text symbolizer definition:
symbolizers:
- text:
    geometry: <expression>
    uom: <text>
    x-composite-base: <boolean>
    x-composite: <text>
    label: <expression>
    fill-color: <color>
    fill-opacity: <expression>
    fill-graphic:
      <graphic_options>
    stroke-graphic:
      <graphic_options>
    stroke-graphic-fill:
      <graphic_options>
    font-family: <expression>
    font-size: <expression>
    font-style: <expression>
    font-weight: <expression>
    placement: <point|line>
    offset: <expression>
    anchor: <tuple>
    displacement: <tuple>
    rotation: <expression>
    halo:
      radius: <expression>
      fill-color: <color>
      fill-opacity: <expression>
      fill-graphic:
        <graphic_options>
    graphic:
      symbols:
        <graphic_options>
      size: <expression>
      opacity: <expression>
      rotation: <expression>
    x-allowOverruns: <boolean>
    x-autoWrap: <expression>
    x-conflictResolution: <boolean>
    x-followLine: <boolean>
    x-forceLeftToRight: <boolean>
    x-goodnessOfFit: <expression>
    x-graphic-margin: <expression>
    x-graphic-resize: <none|proportional|stretch>
    x-group: <boolean>
    x-labelAllGroup: <boolean>
    x-labelPriority: <expression>
    x-repeat: <expression>
    x-maxAngleDelta: <expression>
    x-maxDisplacement: <expression>
    x-minGroupDistance: <expression>
    x-partials: <boolean>
    x-polygonAlign: <boolean>
    x-spaceAround: <expression>
Graphic options used above:
symbols:
- mark:
    shape: <shape>
    <<: *fill
    <<: *stroke
- external:
    url: <text>
    format: <text>
anchor: <tuple>
displacement: <tuple>
opacity: <expression>
rotation: <expression>
size: <expression>
options: <options>
gap: <expression>
initial-gap: <expression>
Fill used above:
fill: &fill
  fill-color: <color>
  fill-opacity: <expression>
  fill-graphic:
    <<: *graphic
Stroke used above:
stroke: &stroke
  stroke-color: <color>
  stroke-width: <expression>
  stroke-opacity: <expression>
  stroke-linejoin: <expression>
  stroke-linecap: <expression>
  stroke-dasharray: <float[]>
  stroke-dashoffset: <expression>
  stroke-graphic-fill:
    <<: *graphic
  stroke-graphic-stroke:
    <<: *graphic
Hints¶
Symbolizer hints are specified as normal mappings on a symbolizer object. Hints start with the prefix ‘x-’ and are limited to numeric, bool and text (no expressions).
If you are checking the GeoServer docs hints are called “vendor options”:
Hints can be used with any symbolizer:
point:
  ...
  # No labels should overlap this feature, used to ensure point graphics are clearly visible
  # and not obscured by text
  x-labelObstacle: true
The majority of hints focus on controlling text:
text:
  # When false does not allow labels on lines to get beyond the beginning/end of the line.
  # By default a partial overrun is tolerated, set to false to disallow it.
  x-allowOverruns: false
  # Number of pixels are which a long label should be split into multiple lines. Works on all
  # geometries, on lines it is mutually exclusive with the followLine option
  x-autoWrap: 400
  # Enables conflict resolution (default, true) meaning no two labels will be allowed to
  # overlap. Symbolizers with conflict resolution off are considered outside of the
  # conflict resolution game, they don't reserve area and can overlap with other labels.
  x-conflictResolution: true
  # When true activates curved labels on linear geometries. The label will follow the shape of
  # the current line, as opposed to being drawn a tangent straight line
  x-followLine: true
  # When true forces labels to a readable orientation, when false they make follow the line
  # orientation even if that means the label will look upside down (useful when using
  # TTF symbol fonts to add direction markers along a line)
  x-forceLeftToRight: true
  # Sets the percentage of the label that must sit inside the geometry to allow drawing
  # the label. Works only on polygons.
  x-goodnessOfFit: 90
  # Pixels between the stretched graphic and the text, applies when graphic stretching is in use
  x-graphic-margin: 10
  # Stretches the graphic below a label to fit the label size. Possible values are 'stretch',
  # 'proportional'.
  x-graphic-resize: true
  # If true, geometries with the same labels are grouped and considered a single entity to be
  # abeled. This allows to avoid or control repeated labels
  x-group: false
  # When false,  only the biggest geometry in a group is labelled (the biggest is obtained by
  # merging, when possible, the original geometries). When true, also the smaller items in the
  # group are labeled. Works only on lines at the moment.
  x-labelAllGroup: false
  # When positive it's the desired distance between two subsequent labels on a "big" geometry.
  # Works only on lines at the moment. If zero only one label is drawn no matter how big the
  # geometry is
  x-repeat: 0
  # When drawing curved labels, max allowed angle between two subsequent characters. Higher
  # angles may cause disconnected words or overlapping characters
  x-maxAngleDelta: 90
  # The distance, in pixel, a label can be displaced from its natural position in an attempt to
  # find a position that does not conflict with already drawn labels.
  x-maxDisplacement: 400
  # Minimum distance between two labels in the same label group. To be used when both
  # displacement and repeat are used to avoid having two labels too close to each other
  x-minGroupDistance: 3
  # Option to truncate labels placed on the border of the displayArea (display partial labels).
  x-partials: true
  # Option overriding manual rotation to align label rotation automatically for polygons.
  x-polygonAlign: true
  # The minimum distance between two labels, in pixels
  x-spaceAround: 50
  # When true enables text kerning (adjustment of space between characters to get a more compact and readable layout)
  x-kerning: true
Additional hints for working with graphic fills:
# Used to specify top, right, bottom and left margins around the graphic used in the fill.
# Allowed values:
# top right bottom left (one explicit value per margin)
x-graphic-margin: 5 10 5 10
# top right-left bottom (three values, with right and left sharing the same value)
x-graphic-margin: 5 10 5
# top-bottom right-left (two values, top and bottom sharing the same value)
x-graphic-margin: 5 10
# top-right-bottom-left (single value for all four margins)
x-graphic-margin: 5
# Activates random distribution of symbol.
# none disables random distribution
x-random: none
# free generates a completely random distribution
x-random: free
# grid will generate a regular grid of positions, and only randomizes the position of the symbol
# around the cell centers, providing a more even distribution in space
x-random: grid
# Determines the size the the texture fill tile that will contain the randomly distributed symbols.
# A smaller tile size will create a more regular pattern
x-random-tile-size: 10
# Activates random symbol rotation. Possible values are none (no rotation) or free.
x-random-rotation: free
# Determines the number of symbols in the tile. Increasing this number will generate a more dense distribution of symbols
x-random-symbol-count: 5
# The “seed” used to generate the random distribution. Changing this value will result in a
# different symbol distribution.
x-random-seed property: 42
Using YSLD¶
YSLD relies on the gt-main style layer descriptor. Style files are parsed to a StyledLayerDescripter object, which can then be used by the GeoTools style renderer.
To read a YSLD style:
StyledLayerDescriptor style = Ysld.parse(ysld);
The value of ysld can be any of java.io.Reader, java.io.InputStream, @link java.io.File or java.lang.String containing a valid YSLD style.
To write a YSLD style, given a Styled Layer Descriptor:
Ysld.encode(sld, output);
The value of output can be any of java.io.Reader, java.io.InputStream, or java.io.File.
YSLD also provides a validator, which can be called using:
Ysld.validate(ysld);
This call accepts the everything that Ysld.parse(ysld) does, and returns a list of exceptions corresponding to syntax errors.