wiki:Help/Validator/MapCSSTagChecker

Languages:

This tagchecker is considered to be the successor of the tagchecker.cfg and uses much of the MapCSS implementation for stylesheets. The official extension for files is *.validator.mapcss.

More complex validator tests, which can not be done with this syntax are realized as Java tests.

Examples

See *.mapcss files in source:trunk/data/validator/ for the checks included in JOSM's core or external validator rules.

*[barrier=wire_fence] {
  throwWarning: tr("{0} is deprecated", "{0.tag}"); /* "{0.tag}" evaluates to "barrier=wire_fence" */
  fixAdd: "barrier=fence"; /* You don't need to remove the barrier key before, it will just override with the new value */
  fixAdd: "fence_type=chain_link";
  assertMatch: "way barrier=wire_fence";
  assertNoMatch: "way barrier=fence";
}

usage of classes:

way[highway=~/^(motorway|trunk|primary|secondary|tertiary)$/] {
  set major_road;
}
way.major_road[!ref] {
  throwOther: tr("highway without {0}", "{1.key}"); /* the class ".major:road" is the 0th selector and "!ref" is the 1st selector. The output is: "highway without ref" */
  assertMatch: "way highway=primary";
  assertNoMatch: "way highway=primary ref=123";
}

Some more details

Syntax

selector {
   /* exactly one of */
   throwError: "message";
   throwWarning: "message";
   throwOther: "message";

   /* arbitrarily many of */
   fixAdd: "key=val";
   fixRemove: "key";
   fixChangeKey: "old=>new";
   fixDeleteObject: this; /* deletes the whole object! */
   suggestAlternative: "any text (e.g., alternative key)";

   /* assertions for unit tests */
   assertMatch: "node/way/relation key1=value1 keyN=valueN";
   assertNoMatch: "node/way/relation key1=value1 keyN=valueN";
}
  • The syntax of selectors is specified in MapCSSImplementation#Selectors
  • Validator rules can be limited to specific countries, see MapCSSImplementation#Territoryselector.
  • Alternatively to strings on the right hand side of those expressions, expressions are evaluated (see list+syntax)
    • Most useful of all is tr() in order to have those strings translated (CLARIFY: where translations for non-core validation rules should be maintained?)
  • If at least one fixAdd/fixRemove/fixChangeKey is specified, those changes are executed for objects matching this test when you press the fix button in the Validator Dialog.
  • If suggestAlternative is/are present, those alternatives are displayed together with the test message
  • assertMatch and assertNoMatch: You can give there examples, which should (assertMatch) or should not (assertNoMatch) match the used selector. So this is a test if the selector works correct for the given example. Normally this is only usefull for more complex selectors and less for simple key-value selectors. The tests are executed in the context of unit tests and on ​jenkins/job/JOSM. They are also executed for local validator files if the advanced option validator.check_assert_local_rules is set to "true" in the advanced preferences (see #10206). If you enabled this option and the test fails, you will get a message in the console output which can look like: WARNUNG: Expecting test '...' to match way ... or ...to not match....
  • Local validator rules do reload automatically, if they are modified and saved by an external application. (The auto reload can stop, if an syntax error in your validator file produces an exception in the console. You need to restart JOSM in this case.)

Placeholders

  • They are used to simplify the translation and make it less error-prone.
  • The placeholders in the warning message e.g. {3} are written with ascending numbers, starting at 0. So: 0 1 2 3 4... This is the id of the placeholder.
  • After the warning message (separated by a comma), you need to define the contents of the placeholders.
  • At first you define the content of the first placeholder (the one with the id 0). Then you define the content of the second placeholder (the one with the id 1), and so on.
  • You need to specify which selector you want to use in the placeholder and if you want to use the key ({i.key}), the value ({i.value}) or the whole tag ({i.tag}) of the selector. Counting starts at 0. So, {4.value} means the value of the 5th selector.
  • Classes and pseudoclasses do also count.
  • You can also use {i.tag} for key only selectors. The message will show the actual value of the key (see #10859).
  • You can use regular expressions in the selector and use this in a placeholder. The message will not show the regexp code but the actual key/value/tag (see #9782).

example:

*[a=b][c=d][e][f=g] {
  throwWarning: tr("{0} BLA {1} BLUB {2} BLIB {3}", "{1.tag}", "{0.key}", "{2.key}", "{3.value}");
}

This will evaluate to c=d BLA a BLUB e BLIB g

node:unconnected:in-downloaded-area[highway=turning_circle] {
  throwWarning: tr("{0} must be connected to a way", "{2.tag}");
}

This will evaluate to highway=turning_circle must be connected to a way. (:unconnected counts as zeroths placeholder and :in-downloaded-area counts as first placeholder, therefore highway=turning_circle is the second placeholder.)

Grouping

  • Different tests can be grouped in the Validator dialog. Example:
node[oneway],
node[bridge],
node[sidewalk],
node[footway] {
  throwWarning: tr("{0}", "{0.tag}");
  group: tr("tag on a node which should be used on a way");
}

results in:

The same grouping text can be used on different rules, see e.g. deprecated.mapcss or even on different validator files.

See also

Last modified 5 months ago Last modified on 2016-11-23T00:13:26+01:00

Attachments (1)

Download all attachments as: .zip