Créer vos propres règles

Créer vos propres règles

La logique des règles

Pour définir vos règles, voici la logique à suivre :

 

  • attribute/mandatory: la ressource NeTEx doit avoir l'attribut donné

    • name: le nom de l’attribut attendu

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

 

  • attribute/blank: l’attribut de la ressource NeTEx doit contenir une valeur (ne peut pas être vide)

    • name: le nom de l’attribut qui doit contenir une valeur

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

 

  • attribute/value: la ressource NeTEx doit avoir une certaine valeur pour un attribut donné

    • name: le nom de l’attribut/élément testé

    • value: la valeur attendue

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

 

  • attribute/match: la ressource NeTEx doit avoir une valeur qui correspond au format donné

    • name: le nom de l’attribut/élément testé

    • value: le format attendu (sous la forme d’une expression régulière)

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

 

  • resource/mandatory: la ressource NeTEx doit être présente

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

 

  • resource/class: la ressource NeTEx doit correspondre à une certaine classe d’objets

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

 

  • collection/count: la ressource NeTEx doit avoir un nombre de valeurs compatible dans une collection donnée

    • collection: le nom de la collection testée

    • minimum_count: le nombre minimum d'éléments attendus dans la collection (optionnel)

    • maximum_count: le nombre maximum d'éléments attendus dans la collection (optionnel)

{ "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: la référence NeTEx d’une certaine classe d’objet doit correspondre à une ressource existante donnée

    • referenced_class: la classe d’object testé

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

 

  • reference/version: la référence NeTEx doit avoir une version correspondante à la valeur donnée

    • referenced_classes: le type de référence testée

    • value: la valeur attendue

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

Par exemple, la règle présente peut tester ces cas:

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

 

  • tag/match: la ressource NeTEx a un tag qui correspond à une expression donnée

    • name: le nom du tag testé

    • value: la valeur du tag attendue (peut-être une expression régulière)

{ "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: vérifie que les horaires de passage des ServiceJourneys sont chronologiques

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

La logique des contextes

  • resource/kind_of: teste seulement les ressources NeTEx avec la ou les classes indiquées

    • resource_classes: liste de classes acceptées

    • resource_class: alias permettant de définir une seule classe acceptée

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

 

  • attribute/match: teste seulement les ressources dans l’attribut indiqué correspondant à la valeur ou l’expression donnée

    • name: le nom de l’attribut testé

    • value: la valeur attendue (peut-être une expression régulière)

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

 

  • reduce/element: teste un élément d’une ressource NeTEx

    • element: le nom de l’élément testé

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

 

  • reduce/collection: teste les ressources présentes dans une ressource NeTEx

    • collection: le nom de la collection contenant les ressources testées

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

La création de vos règles

Client en ligne de commande

C’est la méthode la plus simple pour mettre à jour les règles

  • Créer et mettre à jour un Ruleset :

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

 

  • Récupérer un Ruleset

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

 

  • Éditer simplement un de ses Ruleset :

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

 

  • Supprimer un Ruleset :

secretary-client delete ruleset acmee:test

 

Utilisation de l’API

La documentation complète se trouve dans Postman.

  • Créer et mettre à jour un 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

 

  • Récupérer un Ruleset

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

Retourne une réponse de type :

{ "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" }

 

  • Supprimer un Ruleset:

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

 

Exemples de règles

Règles sur les attributs

  • Vérifie que chaque objet de type Line possède obligatoirement un attribut presentation avec un niveau de criticité warning et un message “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" } ] }

 

  • Vérifie que chaque attribut short_name des objets de type Line et StopPlace contient au maximum 12 caractères avec un niveau de criticité 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" } ] }

 

  • Vérifie la présence de l’attribut colour dans les ressources presentation sur les objets de type Line avec un niveau de criticité 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" } ] } ] }

Règles sur la structure du fichier

  • Vérifie la présence du GeneralFrame ARRET dans le fichier stop.xml du jeu de données en NeTEx avec un niveau de criticité 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>

 

  • Vérifie que les objets Quay, StopPlace et StopPlaceEntrance sont membres d’un 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>