Changes between Version 11 and Version 12 of Rules/PublicTransportGtfs


Ignore:
Timestamp:
2020-07-25T13:43:47+02:00 (6 years ago)
Author:
skyper
Comment:

two more rules; adjusted *_id checks for multiple values; fixes and updates

Legend:

Unmodified
Added
Removed
Modified
  • Rules/PublicTransportGtfs

    v11 v12  
    5757/*  Class  */
    5858
    59 *[type=route_master][route_master =~ /^(bus|share_taxi|trolleybus|train|tram|light_rail|subway|monorail|ferry)$/] {
     59relation[type=route_master][route_master =~ /^(bus|share_taxi|trolleybus|train|tram|light_rail|subway|monorail|ferry)$/] {
    6060  set PtRouteMaster;
    6161}
     
    6565}
    6666
    67 
    68 /*  Rule  */
     67/* relation[type=route_master][gtfs:route_id] > relation { */
     68relation[type=route_master][gtfs:route_id] > * {
     69  set ChildMasterRoute_id;
     70}
     71
     72
     73/*  Rules  */
     74
     75/*  -----------------------
     76 *  missing tag
     77 */
     78
    6979/* {0.tag} without {1.key} (error level) */
    7080
     
    7282
    7383/* {0.tag} without {1.key} (warning level) */
     84
    7485/* stop_position, platform */
    75 *[public_transport][public_transport =~ /^(platform|stop_position)$/][!local_ref],
    76 *[public_transport][public_transport =~ /^(platform|stop_position)$/][!network] {
    77   throwWarning: tr("`{0}` without `{1}*`.", "{0.tag}", "{2.tag}");
    78   group: tr("Public Transport: missing tag");
     86*[public_transport =~ /^(platform|stop_position)$/][public_transport][!local_ref],
     87*[public_transport =~ /^(platform|stop_position)$/][public_transport][!network] {
     88  throwWarning: tr("`{0}` without `{1}*`.", "{1.tag}", "{2.tag}");
     89  group: tr("Public Transport GTFS: missing tag");
    7990  assertMatch:   "node public_transport=stop_position";
    8091  assertMatch:   "way public_transport=platform";
     
    115126relation.PtRoute[type=route][!website] {
    116127  throwWarning: tr("Public transport {0} relation without `{1}*`.", "{1.value}", "{2.tag}");
    117   group: tr("Public Transport: missing tag");
     128  group: tr("Public Transport GTFS: missing tag");
    118129  assertMatch:   "relation type=route route=train";
    119130  assertMatch:   "relation type=route_master route_master=bus";
    120131/* Does not make sense with that many keys above */
    121132/*  assertNoMatch: "relation type=route route=train network:short=MVV";
    122   assertNoMatch: "relation type=route_master route_master=bus colour=green"; */
     133 *  assertNoMatch: "relation type=route_master route_master=bus colour=green";
     134 */
    123135}
    124136
    125137/* {0.tag} without {1.key} or {2.key} (warning level) */
     138
    126139/* stop_position, platform */
    127140*[public_transport][public_transport =~ /^(platform|stop_area|stop_position)$/][!ref:IFOPT][!gtfs:stop_id] {
    128141  throwWarning: tr("`{0}` without `{1}*` or `{2}*`.", "{0.tag}", "{2.tag}", "{3.tag}");
    129   group: tr("Public Transport: missing tag");
     142  group: tr("Public Transport GTFS: missing tag");
    130143  assertMatch:   "node public_transport=stop_position train=yes railway=halt";
    131144  assertNoMatch: "node public_transport=stop_position train=yes railway=stop ref:IFOPT=ch:06666:4";
     
    133146
    134147/* {0.tag} without {1.key}, {2.key} or {3.key} (warning level) */
     148
    135149/* stop_position, platform */
    136150
     
    138152
    139153/* route_master and route relations, ToDo ferry on ways */
    140 relation.PtRouteMaster[gtfs:route_id][!gtfs:feed][!network:guid][!operator:guid],
    141 relation.PtRoute["public_transport:version"=2][!gtfs:shape_id][!gtfs:trip_id][!gtfs:trip_id:sample],
    142 relation.PtRoute[gtfs:route_id][!gtfs:feed][!network:guid][!operator:guid],
    143 relation.PtRoute[gtfs:shape_id][!gtfs:feed][!network:guid][!operator:guid],
    144 relation.PtRoute[gtfs:trip_id][!gtfs:feed][!network:guid][!operator:guid],
    145 relation.PtRoute[gtfs:trip_id:sample][!gtfs:feed][!network:guid][!operator:guid] {
    146   throwWarning: tr("Public transport relation with `{0}` but none of `{1}*`, `{2}*` or `{3}*`.", "{1.tag}", "{2.tag}", "{3.tag}", "{4.tag}");
    147   group: tr("Public Transport: missing tag");
     154relation[gtfs:route_id][!gtfs:feed][!network:guid][!operator:guid].PtRouteMaster,
     155relation["public_transport:version"=2][!gtfs:shape_id][!gtfs:trip_id][!gtfs:trip_id:sample].PtRoute,
     156relation[gtfs:route_id][!gtfs:feed][!network:guid][!operator:guid].PtRoute,
     157relation[gtfs:shape_id][!gtfs:feed][!network:guid][!operator:guid].PtRoute,
     158relation[gtfs:trip_id][!gtfs:feed][!network:guid][!operator:guid].PtRoute,
     159relation[gtfs:trip_id:sample][!gtfs:feed][!network:guid][!operator:guid].PtRoute {
     160  throwWarning: tr("Public transport relation with `{0}` but none of `{1}*`, `{2}*` or `{3}*`.", "{0.tag}", "{1.tag}", "{2.tag}", "{3.tag}");
     161  group: tr("Public Transport GTFS: missing tag");
    148162  assertMatch:   "relation type=route_master route_master=train gtfs:route_id=0-7-242-19j-1";
    149163  assertMatch:   "relation type=route route=bus gtfs:shape_id=0-7-242-19j-1.26.R";
     
    152166}
    153167
    154 /* {0.tag} and {1.tag} without {2.key}, {3.key} or {4.key} (warning level) */
     168/* {0.tag} and {1.tag} without {2.key} (warning level) */
     169
    155170/* stop_position, platform */
    156 node[public_transport][public_transport=stop_position][train=yes][railway!=stop],
    157 *[public_transport][public_transport =~ /^(platform|stop_position)$/][train=yes][!ref] {
    158   throwWarning: tr("`{0}` with `{1}` but without `{2}`.", "{0.tag}", "{2.tag}", "{3.tag}");
    159   group: tr("Public Transport: missing tag");
     171node[public_transport=stop_position][train=yes][railway!=stop][public_transport],
     172*[public_transport =~ /^(platform|stop_position)$/][train=yes][!ref][public_transport] {
     173  throwWarning: tr("`{0}` with `{1}` but without `{2}`.", "{3.tag}", "{1.tag}", "{2.tag}");
     174  group: tr("Public Transport GTFS: missing tag");
    160175  assertMatch:   "node public_transport=stop_position train=yes railway=halt";
    161176  assertNoMatch: "node public_transport=stop_position train=yes railway=stop ref=2";
    162177}
    163178
    164 /* {0.tag} and {1.tag} without {2.key} (warning level) */
     179/* {0.tag} and {1.tag} without {2.key}, {3.key} or {4.key} (warning level) */
     180
    165181/* platform */
    166182*[public_transport=platform][highway=bus_stop][bus!=yes][share_taxi!=yes][trolleybus!=yes] {
    167183  throwWarning: tr("`{0}` with `{1}` but none of `{2}*`, `{3}*` or `{4}*`.", "{0.tag}", "{1.tag}", "{2.tag}", "{3.tag}", "{4.tag}");
    168184  group: tr("Public Transport GTFS: missing tag");
    169   assertMatch: "node public_transport=platform highway=bus_stop";
     185  assertMatch:   "node public_transport=platform highway=bus_stop";
    170186  assertNoMatch: "node public_transport=platform highway=bus_stop bus=yes";
    171187}
    172188
    173 /* value syntax */
    174 
    175 /* FIXME: Get proper syntax as regex displayed.
    176 /* ref:IFOPT, gtfs:stop_id, route/shape/trip_id */
    177 *[gtfs:route_id][gtfs:route_id             !~                           /^[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?$/],
    178 *[gtfs:shape_id][gtfs:shape_id             !~                           /^[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR]$/],
    179 *[gtfs:trip_id][gtfs:trip_id               !~ /^[1-9][0-9]{0,3}\.T[023A]\.[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR]$/],
    180 *[gtfs:trip_id:sample][gtfs:trip_id:sample !~ /^[1-9][0-9]{0,3}\.T[023A]\.[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR]$/] {
     189
     190/*  -----------------------
     191 *  value syntax
     192 */
     193
     194/* ref:IFOPT, gtfs:stop_id, route_id, shape_id, trip_id */
     195/* FIXME: Get proper syntax as regex displayed. */
     196*[gtfs:route_id      ][gtfs:route_id       !~                           /^[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?(;[ ]?[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?)*$/],
     197*[gtfs:shape_id      ][gtfs:shape_id       !~                           /^[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR](;[ ]?[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR])*$/],
     198*[gtfs:trip_id       ][gtfs:trip_id        !~ /^[1-9][0-9]{0,3}\.T[023A]\.[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR](;[ ]?[1-9][0-9]{0,3}\.T[023A]\.[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR])*$/],
     199*[gtfs:trip_id:sample][gtfs:trip_id:sample !~ /^[1-9][0-9]{0,3}\.T[023A]\.[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR](;[ ]?[1-9][0-9]{0,3}\.T[023A]\.[0-9]{1,2}-[1-9][0-9]{0,2}(-[A-Z])?-j[1-9][0-9j]-[1-9][0-9]?\.[1-9][0-9]?\.[HR])*$/] {
    181200  throwError: tr("Value `{0}` for `{1}=*` does not match value syntax.", "{0.value}", "{0.key}");
    182201/*  throwError: tr("Value `{0}` for `{1}=*` does not match value syntax `{2}`.", "{0.value}", "{0.key}", "{1.value}"); */
     
    185204  assertMatch:   "relation gtfs:route_id=7-342-j1j-1.H";
    186205  assertNoMatch: "relation gtfs:route_id=7-342-j1j-1";
     206  assertNoMatch: "relation gtfs:route_id=7-342-j1j-1;7-342-j1j-5";
    187207  assertNoMatch: "relation gtfs:route_id=90-742-B-j20-1";
    188208  assertNoMatch: "relation gtfs:route_id=10-11-I-j20-1";
     
    195215  assertNoMatch: "relation gtfs:trip_id=2.TA.90-742-B-j20-1.4.R";
    196216}
    197 /* FIXME: Get proper syntax as regex displayed.
    198217/* ref:IFOPT, gtfs:stop_id, gtfs:feed, *:guid, gtfs:source_date */
    199 *[gtfs:feed][gtfs:feed         !~ /^(([A-Z]{2}-){2}[a-zA-Z]{2}.*|DE-SPNV|DE-S-und-U-Bahnen|DK-Alle)$/],
    200 *[network:guid][network:guid   !~  /^([A-Z]{2}-){2}[a-zA-Z]{2}.*$/],
     218/* FIXME: Get proper syntax as regex displayed. */
     219*[gtfs:feed    ][gtfs:feed     !~ /^(([A-Z]{2}-){2}[a-zA-Z]{2}.*|DE-SPNV|DE-S-und-U-Bahnen|DK-Alle)$/],
     220*[network:guid ][network:guid  !~  /^([A-Z]{2}-){2}[a-zA-Z]{2}.*$/],
    201221*[operator:guid][operator:guid !~  /^([A-Z]{2}-){2}[a-zA-Z]{2}.*$/],
    202222*[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])$/],
    203 *[ref:IFOPT][ref:IFOPT       !~ /^[a-z]{2}:[0-9]{5}:[1-9][0-9]{0,4}(:[0-9]{1,2}(:[1-9][0-9]?)?)?$/],
     223*[ref:IFOPT   ][ref:IFOPT    !~ /^[a-z]{2}:[0-9]{5}:[1-9][0-9]{0,4}(:[0-9]{1,2}(:[1-9][0-9]?)?)?$/],
    204224*[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]?)?)?$/] {
    205225  throwError: tr("Value `{0}` for `{1}=*` does not match value syntax.", "{0.value}", "{0.key}");
     
    224244}
    225245
    226 /*  ----------------
     246/* route_id, shape_id, trip_id */
     247*[gtfs:route_id      ][count(split(";", tag("gtfs:route_id"))) > 1],
     248*[gtfs:shape_id      ][count(split(";", tag("gtfs:shape_id"))) > 1],
     249*[gtfs:trip_id       ][count(split(";", tag("gtfs:trip_id"))) > 1],
     250*[gtfs:trip_id:sample][count(split(";", tag("gtfs:trip_id:sample"))) > 1] {
     251  throwOther: tr("Multiple values `{0}` for `{1}=*`.", "{0.value}", "{0.key}");
     252  group: tr("Public Transport GTFS: value syntax");
     253  set MultipleID;
     254  assertMatch:   "relation gtfs:route_id=7-342-j1j-1;7-342-j1j-5";
     255  assertNoMatch: "relation gtfs:route_id=7-342-j1j-1.H";
     256}
     257
     258
     259/*  -----------------------
    227260 *  conflicting tags
    228261 */
    229262
    230263/* route_id, shape_id, trip_id */
     264/* FIXME: How to check proper syntax with multiple values */
    231265*[gtfs:trip_id][gtfs:trip_id:sample][!(tag("gtfs:trip_id") == tag("gtfs:trip_id:sample"))] {
    232266throwError: tr("`{1}` and `{0}` are not equal.", "{0.tag}", "{1.tag}");
     
    235269  assertNoMatch: "relation gtfs:trip_id:sample=1108.T2.11-4-I-j20-1.10.H gtfs:trip_id=1108.T2.11-4-I-j20-1.10.H";
    236270}
    237 *[gtfs:shape_id][gtfs:trip_id       ]!.GtfsIdSyntax[!(tag("gtfs:shape_id") == get(regexp_match("^[1-9][0-9]{0,3}\\.T[023A]\\.(.+)$", tag("gtfs:trip_id")), 1))],
    238 *[gtfs:shape_id][gtfs:trip_id:sample]!.GtfsIdSyntax[!(tag("gtfs:shape_id") == get(regexp_match("^[1-9][0-9]{0,3}\\.T[023A]\\.(.+)$", tag("gtfs:trip_id:sample")), 1))],
    239 *[gtfs:route_id][gtfs:shape_id      ]!.GtfsIdSyntax[!(tag("gtfs:route_id") == get(regexp_match("^(.+)\\.[1-9][0-9]?\\.[HR]$", tag("gtfs:shape_id")), 1))],
    240 *[gtfs:route_id][gtfs:trip_id       ]!.GtfsIdSyntax[!(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))],
    241 *[gtfs:route_id][gtfs:trip_id:sample]!.GtfsIdSyntax[!(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))] {
     271*[gtfs:route_id]!.MultipleID!.GtfsIdSyntax[gtfs:shape_id      ][!(tag("gtfs:route_id") == get(regexp_match("^(.+)\\.[1-9][0-9]?\\.[HR]$", tag("gtfs:shape_id")), 1))],
     272*[gtfs:route_id]!.MultipleID!.GtfsIdSyntax[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))],
     273*[gtfs:route_id]!.MultipleID!.GtfsIdSyntax[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")), 3))],
     274*[gtfs:shape_id]!.MultipleID!.GtfsIdSyntax[gtfs:trip_id       ][!(tag("gtfs:shape_id") == get(regexp_match("^[1-9][0-9]{0,3}\\.T[023A]\\.(.+)$", tag("gtfs:trip_id")), 1))],
     275*[gtfs:shape_id]!.MultipleID!.GtfsIdSyntax[gtfs:trip_id:sample][!(tag("gtfs:shape_id") == get(regexp_match("^[1-9][0-9]{0,3}\\.T[023A]\\.(.+)$", tag("gtfs:trip_id:sample")), 1))] {
    242276  throwError: tr("`{1}` is not a substring of `{0}`.", "{0.tag}", "{1.tag}");
    243277  group: tr("Public Transport GTFS: conflicting tags");
    244278  assertMatch:   "relation gtfs:route_id=7-342-j1j-1 gtfs:shape_id=7-352-j1j-1.17.H";
    245279  assertNoMatch: "relation gtfs:route_id=7-342-j1j-1 gtfs:shape_id=7-342-j1j-1.17.H";
    246   assertNoMatch: "relation gtfs:route_id=7-342-j1j-1 gtfs:shape_id=7-342-j-1.17.H";
    247280  assertMatch:   "relation gtfs:route_id=11-4-I-j20-1 gtfs:trip_id=1108.T2.11-5-I-j20-1.10.H";
    248281  assertNoMatch: "relation gtfs:route_id=11-4-I-j20-1 gtfs:trip_id=1108.TB2.11-5-I-j20-1.10.H";
     
    251284
    252285/* route_id parent */
    253 
    254 /* Does not work */
    255 /* relation.PtRouteMaster[gtfs:route_id] > * {
    256  *   set ChildMasterRoute_id;
    257  * }
    258  */
    259 
    260 relation[type=route_master][gtfs:route_id] > relation {
    261   set ChildMasterRoute_id;
    262 }
    263 
     286/* FIXME: How to ckeck with multiple values? */
    264287/* FIXME: How to display the key-value of the parent? */
    265 relation.ChildMasterRoute_id[gtfs:shape_id][parent_tag("gtfs:route_id")][!gtfs:route_id][!(parent_tag("gtfs:route_id") == replace(tag("gtfs:shape_id"), "\\.\\d+\\.[HR]$", ""))],
    266 relation.ChildMasterRoute_id[gtfs:trip_id][parent_tag("gtfs:route_id")][!gtfs:route_id][!gtfs:shape_id][!(parent_tag("gtfs:route_id") == get(regexp_match("^\\d+\\.T[023A]\\.(.+)\\.\\d+\\.[HR]$", tag("gtfs:trip_id")), 1))],
    267 relation.ChildMasterRoute_id[gtfs:trip_id:sample][parent_tag("gtfs:route_id")][!gtfs:route_id][!gtfs:shape_id][!(parent_tag("gtfs:route_id") == get(regexp_match("^\\d+\\.T[023A]\\.(.+)\\.\\d+\\.[HR]$", tag("gtfs:trip_id:sample")), 1))],
    268 relation.ChildMasterRoute_id[gtfs:route_id][parent_tag("gtfs:route_id")][!(parent_tag("gtfs:route_id") == tag("gtfs:route_id"))] {
    269   throwWarning:  tr("`{0}` conflicts with `gtfs:route_id=*` of the `route_master` relation.", "{1.tag}");
    270 /*  throwWarning:  tr("`{0}` differs to `route_id={1}` of the `route_master` relation.", "{1.tag}", "{2.value}"); */
     288relation[gtfs:route_id      ][parent_tag("gtfs:route_id")]!.MultipleID[count(split(";", parent_tag("gtfs:route_id"))) == 1][!(parent_tag("gtfs:route_id") == tag("gtfs:route_id"))].ChildMasterRoute_id,
     289relation[gtfs:shape_id      ][parent_tag("gtfs:route_id")]!.MultipleID[count(split(";", parent_tag("gtfs:route_id"))) == 1][!gtfs:route_id][!(parent_tag("gtfs:route_id") == get(regexp_match("(.+)\\.\\d+\\.[HR]$", tag("gtfs:shape_id")), 1))].ChildMasterRoute_id,
     290relation[gtfs:trip_id       ][parent_tag("gtfs:route_id")]!.MultipleID[count(split(";", parent_tag("gtfs:route_id"))) == 1][!gtfs:route_id][!gtfs:shape_id][!(parent_tag("gtfs:route_id") == get(regexp_match("^\\d+\\.T[023A]\\.(.+)\\.\\d+\\.[HR]$", tag("gtfs:trip_id")), 1))].ChildMasterRoute_id,
     291relation[gtfs:trip_id:sample][parent_tag("gtfs:route_id")]!.MultipleID[count(split(";", parent_tag("gtfs:route_id"))) == 1][!gtfs:route_id][!gtfs:shape_id][!(parent_tag("gtfs:route_id") == get(regexp_match("^\\d+\\.T[023A]\\.(.+)\\.\\d+\\.[HR]$", tag("gtfs:trip_id:sample")), 1))].ChildMasterRoute_id {
     292  throwWarning:  tr("`{0}` conflicts with `gtfs:route_id=*` of the `route_master` relation.", "{0.tag}");
     293/*  throwWarning:  tr("`{0}` differs to `route_id={1}` of the `route_master` relation.", "{0.tag}", "{1.value}"); */
    271294  group: tr("Public Transport GTFS: conflicting tags");
     295/*  assertMatch:   "relation gtfs:shape_id=10-20-I-j20-1.1.R parent_tag(\"type\")=route_master parent_tag(\"gtfs:route_id\")=10-19-I-j20-1";
     296  assertNoMatch: "relation gtfs:shape_id=10-19-I-j20-1.1.R parent_tag(\"type\")=route_master parent_tag(\"gtfs:route_id\")=10-19-I-j20-1"; */
     297}
     298
     299/* ref:IFOPT, gtfs:stop_id, local_ref */
     300*[public_transport][public_transport =~ /^(platform|stop_position)$/][!(tag("local_ref") == get(regexp_match("^(.*:){4}([1-9][0-9]?)", tag("ref:IFOPT")), 2))][local_ref][ref:IFOPT] {
     301  throwWarning:  tr("`{0}` conflicts with `{1}`.", "{3.tag}", "{4.tag}");
     302  group: tr("Public Transport GTFS: conflicting tags");
     303  assertMatch:   "relation public_transport=platform local_ref=14 ref:IFOPT=de:08315:6504:0:1";
     304  assertNoMatch: "relation public_transport=platform local_ref=14 ref:IFOPT=de:08315:6504:0:14";
     305  assertNoMatch: "relation public_transport=platform local_ref=14 ref:IFOPT=de:08315:6504:14";
     306}
     307
     308
     309/*  -----------------------
     310 *  Geometry
     311 */
     312
     313/* stop_position */
     314/* FIXME: How to use assert with :class and evalexpression? */
     315node[public_transport=stop_position]:unconnected:in-downloaded-area,
     316node[public_transport=stop_position]:unconnected:new {
     317  throwError:  tr("`{0}` is not part of any way.", "{0.tag}");
     318  assertMatch:   "node public_transport=stop_position ";
     319  assertNoMatch: "node public_transport=stop_position :unconnected !:new !:in-downloaded-area";
     320  assertNoMatch: "node public_transport=platform :unconnected :new";
     321/*  assertMatch:   "node public_transport=stop_position :unconnected :in-downloaded-area";
     322 *  assertMatch:   "node public_transport=stop_position :unconnected :new";
     323 *  assertNoMatch: "node public_transport=stop_position :unconnected !:new !:in-downloaded-area";
     324 *  assertNoMatch: "node public_transport=platform :unconnected :new";
     325 */
    272326}
    273327