Create your own rules

Create your own rules

The rules logic

To define your rules, here is the logic to follow:

 

  • attribute/mandatory: the NeTEx resource must have the given attribute

    • name: name of the expected attribute

{ "rule": "attribute/mandatory", "name": "name" }

 

  • attribute/blank: the NeTEx resource must have a value for the given attribute (it cannot be blank)

    • name: name of the attribute that cannot be blank

{ "rule": "attribute/blank", "name": "quay_type" }

 

  • attribute/value: the NeTEx resource must have a given value for the given attribute

    • name: name of the attribute/item tested

    • value: the expected value

{ "rule": "attribute/value", "name": "transport_mode", "value": "bus" }

 

  • attribute/match: the NeTEx resource must have a value for the given attribute, which matches a given expression

    • name: name of the attribute/item tested

    • value: the expected expression (regular expression)

{ "rule": "attribute/match", "name": "id", "value": "/DE:.*:LOC/", "message": "Identifier must use this format 'DE:*:LOC'" }

 

  • resource/mandatory: the NeTEx resource must be present (it is mandatory to have it)

{ "rule_context": "resource/kind_of", "resource_class": "Network", "rules": [ { "rule": "resource/mandatory", "message": "A Network is mandatory" } ] }

 

  • resource/class: the NeTEx resource must have comply with the given class

{ "rule_context": "resource/kind_of", "resource_class": "JourneyPattern", "rules": [ { "rule": "resource/class", "expected_class": "ServiceJourneyPattern" "message": "Use ServiceJourneyPattern (not JourneyPattern)" } ] }

 

  • collection/count: the NeTEx resource must have a compatible count of elements in the given collection

    • collection: name of the tested collection

    • minimum_count: minimum count expected in the collection (optional)

    • maximum_count: maximum count expected in the collection (optional)

{ "rule_context": "resource/kind_of", "resource_class": "JourneyPattern", "rules": [ { "rule": "collection/count", "collection": "points_in_sequence", "minimum_count": 2, "message": "A (Service)JourneyPattern has two or more pointsInSequence" } ] }

 

  • reference/exists: the NeTEx reference of the given class must match an existing resource

    • referenced_class: the object class, that is tested

{ "rule": "reference/exist", "referenced_class": "Quay", "message": "All referenced Quays must defined" }

 

  • reference/version: the NeTEx reference must have a version that matches the given value

    • referenced_classes: the type of reference, that is tested

    • value: expected value

{ "rule": "reference/version", "referenced_classes": ["Quay", "StopPlace"], "value": "any" }

For example, the rule below can test these cases:

<PassengerStopAssignment id="valid"> <!-- ... --> <QuayRef version="any" ref="..."/> </PassengerStopAssignment> <PassengerStopAssignment id="unvalid"> <!-- ... --> <QuayRef ref="..."/> </PassengerStopAssignment>

 

  • tag/match: the NeTEx resource has a tag which matches a given expression

    • name: name of the tested tag

    • value: the expected value (can be a regular expression)

{ "rule_context": "resource/kind_of", "resource_class": "ServiceJourney", "rules": [ { "rule": "tag/match", "name": "frame_id", "value": "FR:GeneralFrame:NETEX_HORAIRE:LOC", "message": "ServiceJourneys must be defined in NETEX_HORAIRE GeneralFrame" } ] }

 

  • service_journey/passing_times_chronology: checks that the passing times in ServiceJourneys are chronological

{ "rule": "service_journey/passing_times_chronology", "message": "TimedPassingTimes use chronological passing times" }

The context logic

  • resource/kind_of: tests limited to the NeTEx resource with the given class(es)

    • resource_classes: list of the classes that are permitted

    • resource_class: alias for a single class that is permitted

{ "rule_context": "resource/kind_of", "resource_classes": ["Quay", "StopPlace","StopPlaceEntrance"] "rules": [ ... ] }, { "rule_context": "resource/kind_of", "resource_class": "Line", "rules": [ ... ] }

 

  • attribute/match: tests limited to the given attributed, for which the match to a single value is checked

    • name: name of the tested attributed

    • value: expected value (can be a regular expression)

{ "rule_context": "attribute/match", "name": "id", "value": "FR:GeneralFrame:NETEX_ARRET:LOC", "rules": [ ... ] }

 

  • reduce/element: tests limited to a NeTEx element

    • element: name of the tested element

{ "rule_context": "reduce/element", "element": "presentation", "rules": [ ... ] }

 

  • reduce/collection: test limited to the resources present in a NeTEx collection

    • collection: name of the collection containgin the resources to be tested

{ "rule_context": "reduce/collection", "element": "passingTimes", "rules": [ ... ] }

Creation your own rules

Using the command line

It is the easiest way to update your rules set.

  • Create and update a Ruleset :

secretary-client create ruleset --name="Test Ruleset" --slug=acmee:test sample.json secretary-client patch ruleset acmee:test --definition sample.json

 

  • Fetch a Ruleset

secretary-client get ruleset acmee:test secretary-client get ruleset --definition acmee:test

 

  • Edit simply one of your Rulesets :

secretary-client get ruleset --definition acmee:test > sample.json # Edit sample.json secretary-client update ruleset acmee:test --definition sample.json

 

  • Delete a Ruleset :

secretary-client delete ruleset acmee:test

 

Use of the API

The documentation is available in Postman.

  • Create and update a Ruleset :

➜ curl -s -X POST -H "Authorization: Token token=$TOKEN" -H "Content-Type: application/json; charset=UTF-8" https://chouette-valid.enroute.mobi/api/rulesets -d@- <<EOF { "ruleset": { "name":"Test Ruleset", "slug":"test", "definition":"[ { \"rule\": \"attribute/mandatory\", \"name\": \"name\", \"criticity\": \"error\", \"code\": \"sample\", \"message\": \"Phasellus vel nulla vel dolor semper tincidunt a vitae risus\" } ]" } } EOF
➜ curl -s -X PUT -H "Authorization: Token token=$TOKEN" -H "Content-Type: application/json; charset=UTF-8" https://chouette-valid.enroute.mobi/api/rulesets/test -d@- <<EOF { "ruleset": { "name":"Test Ruleset", "slug":"test", "definition":"[ { \"rule\": \"attribute/mandatory\", \"name\": \"name\", \"criticity\": \"warning\", \"code\": \"sample\", \"message\": \"Fusce in risus ut nisi efficitur tempor et sed ligula\" } ]" } } EOF

 

  • Fetch a Ruleset

➜ curl -s -H "Authorization: Token token=$TOKEN" https://chouette-valid.enroute.mobi/api/rulesets/test | jq .

Typical response:

{ "id": "b97e25fc-ebe0-4417-a8f4-7b1da843d645", "name": "Test Ruleset", "slug": "test", "definition": "[ { \"rule\": \"attribute/mandatory\", \"name\": \"name\", \"criticity\": \"error\", \"code\": \"sample\", \"message\": \"Phasellus vel nulla vel dolor semper tincidunt a vitae risus\" } ]", "created_at": "2025-09-08T07:36:43.076Z", "updated_at": "2025-09-08T07:36:43.076Z" }

 

  • Delete a Ruleset:

➜ curl -s -X DELETE -H "Authorization: Token token=$TOKEN" https://chouette-valid.enroute.mobi/api/rulesets/test

 

Examples of rules

Rules on attributes

  • Checks that each Line object has an attribute presentation with a criticity level “warning” and an error message that is “A Line should have a Presentation”.

{ "rule_context": "resource/kind_of", "resource_classes": "Line", "rules": [ { "rule":"attribute/mandatory", "name": "presentation", "criticity": "warning", "code": "line-presentation-mandatory", "message": "A Line should have a Presentation" } ] }

 

  • Checks that each attribute short_name in the objects Line and StopPlace has a maximum of 12 caracters with a criticity level “error”.

{ "rule_context": "resource/kind_of", "resource_classes": ["StopPlace", "Line"], "rules": [ { "rule": "attribute/match", "name": "short_name", "value": "/^.{0,12}$/", "criticity": "error", "code": "shortname-length", "message": "A ShortName must not exceed 12 characters" } ] }

 

  • Checks that there is an attribute colour in the resources presentation for Line objectfs with a criticity level “warning”.

{ "rule_context": "resource/kind_of", "resource_class": "Line", "rules": [ { "rule_context": "reduce/element", "element": "presentation", "rules": [ { "rule": "attribute/mandatory", "name": "colour", "criticity": "warning", "code": "line-presentation-colour-mandatory", "message": "A Line should have a Presentation color" } ] } ] }

Rules of the file structure

  • Checks that there is a GeneralFrame “ARRET” in the file stop.xml of the NeTEx dataset with a criticity level “error”.

{ "rule_context": "resource/kind_of", "resource_classes": ["GeneralFrame"], "rules": [ { "rule_context": "attribute/match", "name": "id", "value": "FR:GeneralFrame:NETEX_ARRET:LOC", "rules": [ { "rule": "tag/match", "name": "filename", "value": "stop.xml", "criticity": "error", "code": "general-frame-arret-filename", "message": "GeneralFrame ARRET must be in stop.xml" } ] } ] }

 

<!-- stop.xml --> <?xml version="1.0" encoding="utf-8"?> <PublicationDelivery …> <PublicationTimestamp>2023-01-01T00:00:00.0Z</PublicationTimestamp> <ParticipantRef>Exemple</ParticipantRef> <dataObjects> <GeneralFrame id="FR:GeneralFrame:NETEX_ARRET:LOC" version="1.09:FR-NETEX-2.1-1.0"> <TypeOfFrameRef ref="FR:TypeOfFrame:NETEX_ARRET:"/> <members> </members> </GeneralFrame> </dataObjects> </PublicationDelivery>

 

  • Chekcs that the objects Quay, StopPlace and StopPlaceEntrance are part of the a GeneralFrame “Arrêt”

{ "rule_context": "resource/kind_of", "resource_classes": ["Quay", "StopPlace","StopPlaceEntrance"], "rules": [ { "rule": "tag/match", "name": "frame_id", "value": "FR:GeneralFrame:NETEX_ARRET:LOC", "criticity": "error", "code": "...", "message": "..." } ] }

 

<?xml version="1.0" encoding="utf-8"?> <PublicationDelivery …> <PublicationTimestamp>2023-01-01T00:00:00.0Z</PublicationTimestamp> <ParticipantRef>Exemple</ParticipantRef> <dataObjects> <GeneralFrame id="FR:GeneralFrame:NETEX_ARRET:LOC"> <members> <!-- STOP PLACE QUAY TOPOGRAPHIC PLACE STOP PLACE ENTRANCE GENERAL GROUP OF ENTITIES --> </members> </GeneralFrame> </dataObjects> </PublicationDelivery>