Modify

Opened 4 years ago

Last modified 4 years ago

#19504 new enhancement

Better documentation of mapcss validator rules syntax

Reported by: skyper Owned by: team
Priority: normal Milestone:
Component: Wiki content Version:
Keywords: mapcss validator rules Cc:

Description

Currently, there is no page for the validator rules mapcss syntax. Everything is documented at MapCSSImplementation. This leads to problems, as some specific validator parts like throwError is not explained at all and any complex example for validator rules is missing. Additionally, it is not clear which part is valid for rules at all and the context is spread across the big page.

Could we somehow update the situation, please, like explicitly mentioning validator one the relevant parts and adding examples for both, styles and rules, could enhance the situation.

E.g.

  • I miss a concrete example with regexp_match and throwWarning using parts of it of the message.
  • Why are expressions not handled within throwWarning and how to nicely get the values of tags which appear in a negative regexpression?

Thanks a lot.

Attachments (0)

Change History (8)

comment:1 by Klumbumbus, 4 years ago

The validator specific parts are at wiki:/Help/Validator/MapCSSTagChecker

in reply to:  description ; comment:2 by Klumbumbus, 4 years ago

Replying to skyper:

how to nicely get the values of tags which appear in a negative regexpression?

like this?

way[highway][highway!~/^(primary|secondary)$/] {
  throwWarning: tr("highway not primary or secondary but {0}", "{0.value}");
}

in reply to:  2 ; comment:3 by skyper, 4 years ago

Replying to Klumbumbus:

The validator specific parts are at wiki:/Help/Validator/MapCSSTagChecker

Oh, I oversaw the second link, did separate them mean-while. Still there is no indication on wiki:/Help/Styles/MapCSSImplementation about what is working in rules (under certain conditions) and what is exclusively for styles.

Replying to Klumbumbus:

Replying to skyper:

how to nicely get the values of tags which appear in a negative reg-expression?

like this?

way[highway][highway!~/^(primary|secondary)$/] {
  throwWarning: tr("highway not primary or secondary but {0}", "{0.value}");
}

Yeah, thanks, figured that out already. Do not remember exactly, what I had in mind. It was a negative regex including key-value combinations, so I had a list of tags to check which where not present in the selectors.

I have a new problem with a positive regex. How to better format a list:

way[highway][/^.*;lanes$/][!lanes] {
  throwWarning: tr("{0} with {1} but without {2}", "{0.key}", "{1.key}", "{2.key}");
}

Operators within the definition are not evaluated neither works:
-lanesTags: "join_list(", ", tagregex("^.*:lanes$"))";
I want to get the list of keys or even all tags with key ending :lanes.
I also tried "Eval Expressions" but I did not figure out how to use regexp_match and get the job done.

Does subsetting in rules work?

*[type=route_master][route_master =~ /^(bus|share_taxi|trolleybus|train|tram|light_rail|subway|monorail|ferry)$/] {
  set PtRouteMaster
}

*[!network].PtRouteMaster,
*[!operator].PtRouteMaster {
  throwWarning: tr("Public transport relation without {0}", "{0.key}");
}

in reply to:  3 comment:4 by skyper, 4 years ago

Replying to skyper:


Does subsetting in rules work?

*[type=route_master][route_master =~ /^(bus|share_taxi|trolleybus|train|tram|light_rail|subway|monorail|ferry)$/] {
  set PtRouteMaster
}

*[!network].PtRouteMaster,
*[!operator].PtRouteMaster {
  throwWarning: tr("Public transport relation without {0}", "{0.key}");
}

This works see e.g. source:/trunk/resources/data/validator/highway.mapcss

comment:5 by skyper, 4 years ago

How do I get the used negative regex displayed in the warning?
Following does not work and I get:

SEVERE: Unable to replace argument ^[1-9][0-9]?-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR]$ in Value `7-342-j1J-1.19` for `gtfs:shape_id: Illegal group reference: group index is missing: java.lang.IllegalArgumentException: Illegal group reference: group index is missing
/* value syntax */

/* ref:IFOPT, gtfs:stop_id, route/shape/trip_id */
*[gtfs:route_id][gtfs:route_id             !~                           /^[1-9][0-9]?-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?$/],
*[gtfs:shape_id][gtfs:shape_id             !~                           /^[1-9][0-9]?-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR]$/],
*[gtfs:trip_id][gtfs:trip_id               !~ /^[1-9][0-9]{0,3}\.T[023A]\.[1-9][0-9]?-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR]$/],
*[gtfs:trip_id:sample][gtfs:trip_id:sample !~ /^[1-9][0-9]{0,3}\.T[023A]\.[1-9][0-9]?-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR]$/],
*[gtfs:feed][gtfs:feed         !~ /^(([A-Z]{2}-){2}[a-zA-Z]{2}.*|DE-SPNV|DE-S-und-U-Bahnen|DK-Alle)$/],
*[network:guid][network:guid   !~  /^([A-Z]{2}-){2}[a-zA-Z]{2}.*$/],
*[operator:guid][operator:guid !~  /^([A-Z]{2}-){2}[a-zA-Z]{2}.*$/],
*[gtfs:source_date][gtfs:source_date !~ /^20(1[7-9]|20)-(0[1-9]|1[0-2])-(3[01]|[12][0-9]|0[1-9])$/],
*[ref:IFOPT][ref:IFOPT       !~ /^[a-z]{2}:[0-9]{5}:[1-9][0-9]{0,4}(:[0-9]{1,2}(:[1-9][0-9]?)?)?$/],
*[gtfs:stop_id][gtfs:stop_id !~ /^[a-z]{2}:[0-9]{4,5}:[1-9][0-9]{0,4}(:[0-9]{1,2}(:[1-9][0-9]?)?)?$/] {
  throwError: tr("Value `{0}` for `{1}=*` does not match value syntax `{2}`", "{0.value}", "{0.key}", "{1.value}");
  group: tr("Public Transport GTFS");
  assertMatch: "relation gtfs:route_id=7-342-j1j-1.H";
  assertNoMatch: "relation gtfs:route_id=7-342-j1j-1";
  assertNoMatch: "relation gtfs:route_id=90-742-B-j20-1";
  assertNoMatch: "relation gtfs:route_id=10-11-I-j20-1";
  assertMatch: "relation gtfs:shape_id=11-4-I-j20-1.23.";
  assertNoMatch: "relation gtfs:shape_id=11-4-I-j20-1.23.H";
  assertNoMatch: "relation gtfs:shape_id=7-342-j1j-1.51.R";
  assertMatch: "relation gtfs:trip_id=108.T2.11-4-I-j20-1.10.";
  assertNoMatch: "relation gtfs:trip_id=1108.T2.11-4-I-j20-1.10.H";
  assertNoMatch: "relation gtfs:trip_id=29.T0.7-342-j1j-1.50.H";
  assertNoMatch: "relation gtfs:trip_id=2.TA.90-742-B-j20-1.4.R";
  assertMatch: "relation gtfs:feed=DE-SH.NAH";
  assertNoMatch: "relation gtfs:feed=df-SL-saarVV";
  assertNoMatch: "relation gtfs:feed=DE-SH-NAH.SH";
  assertNoMatch: "relation gtfs:feed=DE-BY-VVM-Mittelschwaben";
  assertNoMatch: "relation gtfs:feed=DE-SL-saarVV";
  assertMatch: "relation gtfs:source_date=2016-09-30";
  assertMatch: "relation gtfs:source_date=2020-9-3";
  assertMatch: "relation gtfs:source_date=2016-09-30";
  assertNoMatch: "relation gtfs:source_date=2020-09-30";
  assertMatch: "node ref:IFOPT=+1";
  assertMatch: "node ref:IFOPT=aa:aa:09";
  assertMatch: "node ref:IFOPT=ch:3001:64883";
  assertNoMatch: "node ref:IFOPT=ch:23001:64883";
  assertNoMatch: "node ref:IFOPT=de:08315:6504:0:14";
  assertNoMatch: "node ref:IFOPT=ch:23005:6";
  assertNoMatch: "node gtfs:stop_id=ch:3001:64883";
}
Last edited 4 years ago by skyper (previous) (diff)

comment:6 by skyper, 4 years ago

Damn no word about handling of dots . as string in regexp_match. Needs two backslash \\:

*[gtfs:route_id][gtfs:shape_id]["gtfs:route_id" != get(regexp_match("^(.+)\\.[1-9][0-9]?\\.[HR]$", tag("gtfs:shape_id")), 1)]  {

in reply to:  6 comment:7 by skyper, 4 years ago

Replying to skyper:

Damn no word about handling of dots . as string in regexp_match. Needs two backslash \\:

*[gtfs:route_id][gtfs:shape_id]["gtfs:route_id" != get(regexp_match("^(.+)\\.[1-9][0-9]?\\.[HR]$", tag("gtfs:shape_id")), 1)]  {

Does not work and the assertMatch does not warn. Below seems to work though:

/* conflicting tags */
/* route_id, shape_id, trip_id */
*[gtfs:route_id][gtfs:shape_id][!(tag("gtfs:route_id") == get(regexp_match("^(.+)\\.[1-9][0-9]?\\.[HR]$", tag("gtfs:shape_id"), "d"), 1))],
*[gtfs:route_id][gtfs:trip_id][!(tag("gtfs:route_id") == get(regexp_match("^[1-9][0-9]{0,3}\\.T[023A]\\.(.+)\\.[1-9][0-9]?\\.[HR]$", tag("gtfs:trip_id")), 1))],
*[gtfs:route_id][gtfs:trip_id:sample][!(tag("gtfs:route_id") == get(regexp_match("^[1-9][0-9]{0,3}\\.T[023A]\\.(.+)\\.[1-9][0-9]?\\.[HR]$", tag("gtfs:trip_id:sample")), 1))] {
  throwError: tr("`{1}` is not a substring of `{0}`", "{0.tag}", "{1.tag}");
  group: tr("Public Transport GTFS");
  assertMatch:   "relation gtfs:route_id=7-342-j1j-1 gtfs:shape_id=7-342-j1j-1";
  assertMatch:   "relation gtfs:route_id=7-342-j1j-1 gtfs:shape_id=7-352-j1j-1.17.H";
  assertMatch:   "relation gtfs:route_id=7-342-j1j-1 gtfs:shape_id=T7-342-j1j-1.17.H";
  assertNoMatch: "relation gtfs:route_id=7-342-j1j-1 gtfs:shape_id=7-342-j1j-1.17.H";
  assertMatch:   "relation gtfs:route_id=11-4-I-j20-1 gtfs:trip_id=1108.T2.11-4-I-j20-1.10.";
  assertMatch:   "relation gtfs:route_id=11-4-I-j20-1 gtfs:trip_id=1108.T2.11-5-I-j20-1.10.H";
  assertMatch:   "relation gtfs:route_id=11-4-I-j20-1 gtfs:trip_id=1108.TB2.11-5-I-j20-1.10.H";
  assertNoMatch: "relation gtfs:route_id=11-4-I-j20-1 gtfs:trip_id=1108.T2.11-4-I-j20-1.10.H";
}
Last edited 4 years ago by skyper (previous) (diff)

comment:8 by skyper, 4 years ago

I have more questions, see #16977.

skyper (comment 7):

Replying to GerdP:


It seems that these rules in addresses.mapcss are matched although there is no way in the dataset:

way[addr:interpolation=odd] > node[addr:housenumber][get(split(".", tag("addr:housenumber")/2), 1)=0] {
    throwWarning: tr("Even housenumber in odd address interpolation.");
}
way[addr:interpolation=even] > node[addr:housenumber][get(split(".", tag("addr:housenumber")/2), 1)=5] {
    throwWarning: tr("Odd housenumber in even address interpolation.");
}

It seems that the selector works in the wrong way?

How about:

way[addr:interpolation =~ /^(even|odd)$/] > node ( set ChildAddrInterpol;}

node[addr:housenumber]get(split(".", tag("addr:housenumber")/2), 1)=0].ChildAddrInterpol {
    throwWarning: tr("Even housenumber in odd address interpolation.");
}
node[addr:housenumber][get(split(".", tag("addr:housenumber")/2), 1)=5].ChildAddrInterpol {
    throwWarning: tr("Odd housenumber in even address interpolation.");
}

Does the order of selectors matter? From which side is evaluated?

Maybe even below will work, which will only look for parent tag:

node[addr:housenumber][parent_tag("addr:interpolation") == odd][get(split(".", tag("addr:housenumber")/2), 1)=0] {
    throwWarning: tr("Even housenumber in odd address interpolation.");
}
node[addr:housenumber][parent_tag("addr:interpolation") == even][get(split(".", tag("addr:housenumber")/2), 1)=5] {
    throwWarning: tr("Odd housenumber in even address interpolation.");
}

At least for performance, it would be good to know in which order the selectors are evaluated and if it is useful to add a child/parent selector as class at the end or at the beginning. Can anyone tell me something about it?

Modify Ticket

Change Properties
Set your email in Preferences
Action
as new The owner will remain team.
as The resolution will be set. Next status will be 'closed'.
to The owner will be changed from team to the specified user.
Next status will be 'needinfo'. The owner will be changed from team to skyper.
as duplicate The resolution will be set to duplicate. Next status will be 'closed'. The specified ticket will be cross-referenced with this ticket.
The owner will be changed from team to anonymous. Next status will be 'assigned'.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.