Lenex Parser
Lenex Parser is a streaming Lenex 3 parser built on Nokogiri's SAX interface. It incrementally assembles the object graph without materialising the full DOM, keeping memory usage low even for multi-megabyte swim meet exports.
Installation
Add this line to your application's Gemfile:
gem 'lenex-parser'And then execute:
bundle installOr install it yourself as:
gem install lenex-parserUsage
Loading the library
# Load the entire gem (parser, document builder, and value objects)
require 'lenex-parser'
# Load only the streaming parser API
require 'lenex/parser'
# Load just the document builder and value objects for manual construction flows
require 'lenex/document'
require 'lenex/parser/objects'Requiring lenex-parser gives you access to the streaming parser, Lenex::Document, and all of the value objects used in the builder. The rest of the examples assume you have loaded the gem this way. If you prefer finer-grained requires, use the targeted options shown above.
Parsing Lenex XML
require 'lenex-parser'
xml = File.read('meet.lenex')
lenex = Lenex::Parser.parse(xml)
puts "Lenex version: #{lenex.version}"
puts "Revision: #{lenex.revision}"
puts "Built by: #{lenex.constructor.name} (#{lenex.constructor.version})"
puts "Contact email: #{lenex.constructor.contact.email}"Lenex::Parser.parse accepts any IO-like object (such as a File opened in binary mode) or a raw XML string. When given an IO it reads chunk-by-chunk, emitting SAX events into the builder so the full XML tree is never loaded at once. You can also hand it a filesystem path (as a String or Pathname) and the parser will open the file in binary mode for you before streaming. Strings that contain XML or ZIP bytes are always treated as in-memory payloads, even if a file with the same name exists on disk.
# Parse directly from a file path or Pathname
require 'pathname'
lenex = Lenex::Parser.parse('meet.lenex')
lenex = Lenex::Parser.parse(Pathname.new('meet.lenex.zip'))Traversing deeply nested data
The parser returns a Lenex::Parser::Objects::Lenex instance whose child
collections expose plain Ruby arrays. You can use familiar Enumerable helpers to
drill into the object graph and extract the information you need—even when it
lives several levels deep in the document.
lenex = Lenex::Parser.parse('meet.lenex')
# Grab a specific session by number and inspect one of its events.
first_meet = lenex.meets.first
session_one = first_meet.sessions.detect { |session| session.number == '1' }
first_event = session_one.events.first
puts "Event ##{first_event.number} uses #{first_event.swim_style.stroke}"
# Walk from the meet down to a particular athlete entry.
clubs = first_meet.clubs
sprinter = clubs.flat_map(&:athletes).detect { |athlete| athlete.last_name == 'Phelps' }
entry = sprinter.entries.detect { |e| e.event_id == first_event.event_id }
puts "Lane #{entry.lane} entry time: #{entry.entry_time}"
# Pull the same athlete's official result if it exists.
result = sprinter.results.find { |r| r.event_id == first_event.event_id }
puts "Final time: #{result&.swim_time || 'not recorded'}"Every object provides reader methods that mirror the Lenex schema. For example,
Lenex::Parser::Objects::Club#athletes returns an array of
Lenex::Parser::Objects::Athlete, and each athlete exposes entries, results,
and handicap. The nested arrays are regular Ruby collections, so idioms such
as flat_map, detect, or group_by work out of the box.
Building documents incrementally
The gem also exposes a lightweight Lenex::Document model for callers that need to build Lenex payloads programmatically before exporting them. The class mirrors the <LENEX> root element and provides helpers for accumulating constructor metadata as well as meet, record list, and time-standard list entries.
require 'lenex/document'
require 'lenex/parser/objects'
document = Lenex::Document.new
document.constructor = Lenex::Parser::Objects::Constructor.new(
name: 'LENEX Builder',
registration: 'Example Org',
version: '1.2.3',
contact: Lenex::Parser::Objects::Contact.new(email: 'support@example.com')
)
meet = Lenex::Parser::Objects::Meet.new(
name: 'City Championships',
city: 'Berlin',
nation: 'GER'
)
document.add_meet(meet)
document.record_lists # => []
document.time_standard_lists # => []
# Export the document to Lenex XML
xml = document.to_xml
File.write('export.lenex', xml)
# See examples/build_and_export_document.rb for a complete script that
# assembles meets, record lists, and time standards before exporting.If you have already required lenex-parser, the document builder and object model are loaded and you can omit the more granular requires shown above. Lenex::Document::ConstructorMetadata normalizes all keys to symbols so you can pass either strings or symbols when writing attributes (e.g., constructor['contact'] = contact_details). Each helper method returns the object you passed in, making it easy to chain builder flows.
Building a larger document
The value objects under Lenex::Parser::Objects accept keyword arguments that
mirror their XML attributes. You can compose them to build fully fledged Lenex
payloads before streaming them back out of your application. The following
example assembles a meet with one session, one event, and a single athlete
entry.
require 'lenex/document'
require 'lenex/parser/objects'
require 'nokogiri'
document = Lenex::Document.new(version: '3.0', revision: '2024.1')
contact = Lenex::Parser::Objects::Contact.new(
name: 'Jane Doe',
email: 'jane.doe@example.com',
phone: '+49 30 1234567'
)
constructor = Lenex::Parser::Objects::Constructor.new(
name: 'My Meet Manager',
registration: 'City Aquatics',
version: '2.5.0',
contact: contact
)
document.constructor = constructor
swim_style = Lenex::Parser::Objects::SwimStyle.new(
distance: '100',
relay_count: '1',
stroke: 'FREE'
)
event = Lenex::Parser::Objects::Event.new(
event_id: 'E1',
number: '1',
round: 'PRE',
swim_style: swim_style
)
session = Lenex::Parser::Objects::Session.new(
number: '1',
date: '2024-05-18',
name: 'Morning Heats',
events: [event]
)
athlete = Lenex::Parser::Objects::Athlete.new(
athlete_id: 'A1',
first_name: 'Lena',
last_name: 'Schmidt',
gender: 'F',
birthdate: '2006-02-14',
entries: [
Lenex::Parser::Objects::Entry.new(
event_id: event.event_id,
entry_time: '00:57.34',
lane: '4'
)
]
)
club = Lenex::Parser::Objects::Club.new(
name: 'City Aquatics',
nation: 'GER',
athletes: [athlete]
)
meet = Lenex::Parser::Objects::Meet.new(
name: 'City Championships',
city: 'Berlin',
nation: 'GER',
sessions: [session],
clubs: [club]
)
document.add_meet(meet)
lenex = document.build_lenexAt this point lenex is a Lenex::Parser::Objects::Lenex instance populated
with your meet, ready to be serialised or further enriched.
Exporting to XML and saving to disk
The gem focuses on parsing and provides the document builder for convenience;
it does not ship with a dedicated serializer. Because the value objects expose
plain Ruby readers, you can use Nokogiri::XML::Builder (already a dependency
of the gem) to convert the object graph back into Lenex XML and write it to
disk:
lenex = document.build_lenex
xml = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |builder|
builder.LENEX(version: lenex.version, revision: lenex.revision) do
builder.CONSTRUCTOR(name: lenex.constructor.name,
registration: lenex.constructor.registration,
version: lenex.constructor.version) do
builder.CONTACT(email: lenex.constructor.contact.email)
end
builder.MEETS do
lenex.meets.each do |m|
builder.MEET(name: m.name, city: m.city, nation: m.nation) do
builder.SESSIONS do
m.sessions.each do |s|
builder.SESSION(number: s.number, date: s.date) do
builder.EVENTS do
s.events.each do |e|
builder.EVENT(eventid: e.event_id, number: e.number) do
style = e.swim_style
builder.SWIMSTYLE(distance: style.distance,
relaycount: style.relay_count,
stroke: style.stroke)
end
end
end
end
end
end
builder.CLUBS do
m.clubs.each do |club|
builder.CLUB(name: club.name, nation: club.nation) do
builder.ATHLETES do
club.athletes.each do |athlete|
builder.ATHLETE(athleteid: athlete.athlete_id,
firstname: athlete.first_name,
lastname: athlete.last_name,
gender: athlete.gender,
birthdate: athlete.birthdate) do
builder.ENTRIES do
athlete.entries.each do |entry|
builder.ENTRY(eventid: entry.event_id,
entrytime: entry.entry_time,
lane: entry.lane)
end
end
end
end
end
end
end
end
end
end
end
end
end.to_xml
File.binwrite('city-championships.lenex', xml)Feel free to expand the builder logic with the additional optional attributes
your workflow requires. Because all nested collections are plain arrays, you can
reuse the same patterns shown in the traversal examples to iterate over record
lists, time standards, relay teams, or any other Lenex section you need to
render.
If you have already required lenex-parser, the document builder and object model are loaded and you can omit the more granular requires shown above. Lenex::Document::ConstructorMetadata normalizes all keys to symbols so you can inspect parsed metadata prior to replacing it with a full Lenex::Parser::Objects::Constructor. When exporting, assign a constructor object as shown above to satisfy the Lenex schema requirements. Each helper method returns the object you passed in, making it easy to chain builder flows.
Parsing zipped Lenex files
Lenex::Parser.parse also recognises ZIP archives that contain a .lef or .xml payload and automatically extracts the first matching file. This makes it easy to work with the compressed exports that many federation systems produce:
require 'lenex/parser'
require 'lenex/document'
zip_data = File.binread('meet.lenex.zip')
lenex = Lenex::Parser.parse(zip_data)
puts lenex.constructor.namezip_data can come from anywhere—an HTTP response body, a database blob, or any other in-memory string. The parser inspects the leading bytes to decide whether to unzip or stream the XML directly, so no extra branching is required at the call site.
The parser lazily loads the optional rubyzip dependency the first time a ZIP archive is encountered. Install it ahead of time with gem install rubyzip (or add it to your Gemfile) to keep parsing seamless in production environments.
Example scripts
Run bundle exec ruby examples/builder_and_parser.rb to see a standalone script that constructs a Lenex::Document and parses a minimal Lenex XML payload. The script lives in the examples directory alongside a README that describes how to run it from a checked-out repository.
Object model overview
The parser returns a Lenex::Parser::Objects::Lenex instance that exposes the top-level metadata of the Lenex file:
-
version– Lenex schema version string declared in the<LENEX>root element. -
revision– Revision identifier provided by the source system. -
constructor– ALenex::Parser::Objects::Constructorwith information about who produced the file. -
meets– Array ofLenex::Parser::Objects::Meetdescribing meet level information found under<MEETS>. -
record_lists– Array ofLenex::Parser::Objects::RecordListobjects representing the<RECORDLISTS>section when present. -
time_standard_lists– Array ofLenex::Parser::Objects::TimeStandardListobjects representing<TIMESTANDARDLISTS>when supplied.
The constructor object provides these accessors:
-
name– Application or organisation name responsible for generating the export. -
registration– Registration number reported in the<CONSTRUCTOR>element. -
version– Constructor application version string. -
contact– ALenex::Parser::Objects::Contactcontaining communication details for the file creator.
The contact object yields:
-
email– Email address for follow-up questions. -
phone– Optional phone number if available. -
fax– Optional fax number. -
name– Contact person's full name when supplied.
The meet object exposes:
-
name– Required meet name taken from the<MEET>element. -
name_en– Optional English representation of the meet name. -
city– Required meet city name. -
city_en– Optional English representation of the meet city. -
nation– Required meet nation code. -
course– Optional course attribute describing the pool length. -
entry_type– Optional classification describing whether the meet accepts open or invitation-only entries. -
max_entries_athlete– Optional limit on individual entries per athlete for the entire meet. -
max_entries_relay– Optional limit on relay entries per club for the entire meet. -
reserve_count– Optional number of reserve swimmers tracked for finals. -
start_method– Optional start method flag (1for one-start,2for two-start procedures). -
timing– Optional timing system information recorded at the meet level. -
touchpad_mode– Optional description of the touchpad installation. -
type– Optional meet classification supplied by the federation. -
altitude– Optional venue altitude in metres above sea level. -
swrid– Optional SwimRankings.net identifier for the meet. -
result_url– Optional URL pointing to published meet results. -
contact– OptionalLenex::Parser::Objects::Contactfor the meet organiser when provided. -
age_date– OptionalLenex::Parser::Objects::AgeDatedescribing how to calculate athlete ages for the meet. -
bank– OptionalLenex::Parser::Objects::Bankcontaining payment instructions for entry fees. -
facility– OptionalLenex::Parser::Objects::Facilitydescribing the venue address. -
point_table– OptionalLenex::Parser::Objects::PointTableidentifying the scoring system in use. -
qualify– OptionalLenex::Parser::Objects::Qualifyoutlining qualification period and conversion rules. -
pool– OptionalLenex::Parser::Objects::Pooldescribing lane configuration when the meet defines a default pool. -
fee_schedule– OptionalLenex::Parser::Objects::FeeSchedulecontaining global meet fee definitions. -
host_club– OptionalLenex::Parser::Objects::HostClubwith information about the executing organisation. -
organizer– OptionalLenex::Parser::Objects::Organizerdescribing the promoting body. -
entry_schedule– OptionalLenex::Parser::Objects::EntrySchedulecapturing entry start dates, deadlines, and withdrawal cut-offs. -
clubs– Array ofLenex::Parser::Objects::Clubobjects describing participating clubs. -
sessions– Array ofLenex::Parser::Objects::Sessionobjects capturing the meet schedule.
The age date object exposes:
-
type– Required strategy for calculating ages (e.g.,YEAR,DATE). -
value– Optional reference date when the calculation requires a specific day.
The bank object exposes:
-
account_holder– Optional name attached to the bank account. -
bic– Optional bank identifier code. -
iban– Required IBAN for the receiving account. -
name– Optional bank name. -
note– Optional payment note or reference instructions.
The facility object exposes:
-
city– Required city containing the venue. -
nation– Required nation code for the facility location. -
name– Optional display name of the venue. -
state– Optional state, province, or region for the venue. -
street/street2– Optional address lines. -
zip– Optional postal code for the facility.
The point table object exposes:
-
name– Required name of the scoring system. -
point_table_id– Optional identifier for well-known point tables. -
version– Required edition or year of the scoring system.
The qualify object exposes:
-
conversion– Optional conversion method applied to entry times. -
from– Required start date of the qualification window. -
percent– Optional percentage used when conversion requires it. -
until– Optional end date of the qualification window.
The host club object exposes:
-
name– Host club name responsible for executing the meet. -
url– Optional URL pointing to the host club's website.
The organizer object exposes:
-
name– Organization that promotes the meet. -
url– Optional URL with more details about the organizer.
The entry schedule object exposes:
-
entry_start_date– Optional date when entries open. -
withdraw_until– Optional date by which withdrawals must be submitted. -
deadline_date– Optional entry deadline date. -
deadline_time– Optional entry deadline time.
The club object exposes:
-
name– Full club name when provided (required unless the club type isUNATTACHED). -
name_en– Optional English representation of the club name. -
shortname/shortname_en– Optional abbreviated names for local and English contexts. -
code– Optional national federation club code. -
nation– Optional federation nation code for the club. -
number– Optional differentiator used when a club fields multiple teams. -
region– Optional code for the regional swimming committee. -
swrid– Optional SwimRankings.net identifier. -
type– Optional classification such asCLUB,NATIONALTEAM,REGIONALTEAM, orUNATTACHED. -
contact– OptionalLenex::Parser::Objects::Contactwith meet-specific club contact details.
The session object exposes:
-
number– Required session number unique within a meet. -
date– Required session date inYYYY-MM-DDformat. -
course– Optional pool length overriding the meet-wide course. -
daytime– Optional start time for the session. -
endtime– Optional time the session finished. -
fee_schedule– OptionalLenex::Parser::Objects::FeeSchedulecontaining session-specific fee overrides. -
max_entries_athlete– Optional limit on individual entries per athlete for the session. -
max_entries_relay– Optional limit on relay entries per club for the session. -
name– Optional descriptive session name (e.g., "Day 1 – Prelims"). -
official_meeting– Optional meeting time for officials. -
remarks_judge– Optional referee remarks. -
team_leader_meeting– Optional meeting time for team leaders. -
timing– Optional timing system information for the session. -
touchpad_mode– Optional touchpad mode description. -
warmup_from/warmup_until– Optional warm-up window times. -
pool– OptionalLenex::Parser::Objects::Pooldescribing the lane configuration and environment of the competition pool. -
judges– Array ofLenex::Parser::Objects::Judgeobjects covering the meet officials attached to the session. -
events– Array ofLenex::Parser::Objects::Eventobjects with the events contested in the session.
The event object exposes:
-
event_id– Required identifier unique across all events in a meet (sourced from theeventidattribute). -
number– Required event number within the meet program. -
gender– Optional gender designator (A,M,F, orX). -
round– Optional round identifier such asPRE,SEM, orFIN. -
daytime– Optional scheduled start time for the event. -
max_entries– Optional maximum number of entries per club for the event. -
order– Optional event order overriding the numeric sequence when necessary. -
previous_event_id– Optional identifier of the preceding round for finals progression. -
run– Optional swim-off run counter. -
timing– Optional timing type overriding the session defaults. -
type– Optional event classification (e.g.,MASTERS). -
fee– OptionalLenex::Parser::Objects::Feerepresenting the event specific entry fee. -
swim_style–Lenex::Parser::Objects::SwimStyledescribing the stroke, distance, and relay composition of the event. -
age_groups– Array ofLenex::Parser::Objects::AgeGroupobjects defining eligible age ranges. -
heats– Array ofLenex::Parser::Objects::Heatobjects describing detailed start lists. -
time_standard_refs– Array ofLenex::Parser::Objects::TimeStandardRefobjects referencing applicable time standard lists and optional fines.
The heat object exposes:
-
heat_id– Required identifier unique across all heats within a meet (from theheatidattribute). -
number– Required heat number unique within an event. -
age_group_id– Optional reference to an age group that the heat belongs to. -
daytime– Optional scheduled start time for the heat. -
final– Optional final designator (A,B,C, orD). -
order– Optional order override when heats do not run sequentially. -
status– Optional heat status such asSCHEDULED,SEEDED,INOFFICIAL, orOFFICIAL.
The age group object exposes:
-
age_group_id– Required identifier unique within the event, referenced by entries. -
age_max– Required upper bound of the age range (-1indicates no upper bound). -
age_min– Required lower bound of the age range (-1indicates no lower bound). -
calculate– Optional calculation mode for relay totals (SINGLEorTOTAL). -
gender– Optional gender limitation for the age group (A,M,F, orX). -
handicap– Optional para-swimming handicap class grouping. -
level_max/level_min– Optional bounds restricting athlete levels. -
levels– Optional comma-separated list of explicitly allowed athlete levels. -
name– Optional display name for the age group (e.g., "Juniors"). -
rankings– Array ofLenex::Parser::Objects::Rankingobjects capturing the final placements for the age group within the event.
The swim style object exposes:
-
distance– Required event distance in meters for each competitor (per-leg distance for relays). -
relay_count– Required number of swimmers per entry (use1for individual events). -
stroke– Required stroke enumeration for the event (e.g.,FREE,BACK,MEDLEY). -
code– Optional short code to distinguish custom swim styles when the stroke isUNKNOWN. -
name– Optional descriptive name for unusual swim styles. -
swim_style_id– Optional identifier to uniquely track special swim styles across the meet. -
technique– Optional technique modifier (e.g.,KICK,TURN) for skill-specific events.
The fee object exposes:
-
currency– Optional three-letter currency code describing the fee currency. -
type– Optional fee classification (e.g.,ATHLETE,RELAY,CLUB) used in the context of fee collections. -
value– Required monetary value expressed in cents.
The fee schedule object exposes:
-
fees– Array ofLenex::Parser::Objects::Feeinstances contained in the surrounding<FEES>collection.
The ranking object exposes:
-
place– Required final place within the rankings list. -
result_id– Required identifier referencing the associated result entry. -
order– Optional explicit ordering override for ranking presentation.
The pool object exposes:
-
lane_min– Optional first lane number used during the meet or session. -
lane_max– Optional last lane number available for competition. -
temperature– Optional reported water temperature. -
type– Optional venue type (e.g.,INDOOR,OUTDOOR,LAKE,OCEAN).
The judge object exposes:
-
official_id– Required identifier referencing the official in the meet's official list. -
number– Optional sequencing or lane assignment for the judge. -
role– Optional role descriptor reflecting the official's duties (e.g.,REF,TIK). -
remarks– Optional free-form remarks about the assignment.
The time standard reference object exposes:
-
time_standard_list_id– Required identifier pointing to the referenced time standard list. -
marker– Optional string used to annotate results that met or missed the referenced time standard. -
fee– OptionalLenex::Parser::Objects::Feedescribing fines or penalties linked to the time standard reference.
The athlete object exposes:
-
athlete_id– Required identifier unique to the athlete within the meet. -
birthdate– Required birth date of the athlete inYYYY-MM-DDformat. -
first_name/first_name_en– Required first name and optional English variant. -
last_name/last_name_en– Required last name and optional English variant. -
gender– Required gender flag (MorF). -
level– Optional athlete level string. -
license/license_ipc– Optional federation and IPC license identifiers. -
name_prefix– Optional surname prefix (e.g., "van den"). -
nation– Optional athlete nation code. -
passport– Optional passport number. -
status– Optional status flag such asROOKIE,FOREIGNER, orEXHIBITION. -
swrid– Optional SwimRankings.net identifier. -
handicap– OptionalLenex::Parser::Objects::Handicapdetailing para-swimming classifications for the athlete. -
entries– Array ofLenex::Parser::Objects::Entryrepresenting the athlete's entries. -
results– Array ofLenex::Parser::Objects::Resultrepresenting the athlete's results.
The entry object exposes:
-
event_id– Required reference to the event the entry belongs to. -
entry_time– Optional entry time string. -
status– Optional status flag such asSICKorWDR. -
lane– Optional assigned lane number. -
heat_id– Optional reference to the scheduled heat. -
age_group_id– Optional reference to the event age group. -
entry_course– Optional pool length for the entry time. -
entry_distance– Optional entry distance in centimetres for fin-swimming events. -
handicap– Optional para-swimming sport class override. -
meet_info– OptionalLenex::Parser::Objects::MeetInfodescribing when the entry time was achieved.
The handicap object exposes:
-
breast– Required breaststroke sport class (matching SB codes). -
breast_status– Optional confirmation status for the breaststroke class. -
exception– Optional comma-separated exception codes as defined by WPS rules. -
free– Required freestyle/backstroke/fly sport class (matching S codes). -
free_status– Optional confirmation status for the freestyle/backstroke/fly class. -
medley– Required individual medley sport class (matching SM codes). -
medley_status– Optional confirmation status for the individual medley class.
The meet info object exposes:
-
approved– Optional approving organisation code (e.g.,AQUA,LEN). -
city/state– Optional city and state where the time was achieved. -
course– Optional pool length used for the entry or record. -
date– Optional date when the time was achieved. -
daytime– Optional time of day when the swim occurred. -
name– Optional meet name. -
nation– Optional nation code for the city. -
qualification_time– Optional qualifying time differing from the entry time. -
timing– Optional timing system used for the swim. -
pool– OptionalLenex::Parser::Objects::Pooldescribing the pool where the time was achieved.
The result object exposes:
-
result_id– Required identifier unique to the result within the meet. -
swim_time– Required final swim time string orNT. -
status– Optional status flag such asDSQ,DNS, orEXH. -
comment– Optional free-text comment (e.g., new record remarks). -
event_id– Optional reference to the event. -
heat_id– Optional reference to the heat. -
lane– Optional lane number. -
points– Optional points scored for the swim. -
reaction_time– Optional start reaction time for the swim. -
handicap– Optional para-swimming sport class override. -
swim_distance– Optional distance in centimetres for fin-swimming events. -
splits– Array ofLenex::Parser::Objects::Splitdescribing split times.
The split object exposes:
-
distance– Required split distance in meters. -
swim_time– Required split time for the distance in swim-time format.
The relay object exposes:
-
age_max– Required maximum age for the oldest swimmer on the relay team. -
age_min– Required minimum age for the youngest swimmer on the relay team. -
age_total_max– Required maximum combined age for all swimmers on the team. -
age_total_min– Required minimum combined age for all swimmers on the team. -
gender– Required gender classification for the relay (M,F, orX). -
handicap– Optional para-swimming relay handicap classification. -
name– Optional descriptive team name (e.g., "Mixed Medley A"). -
number– Optional team number used when clubs field multiple relays in the same age group. -
relay_positions– Array ofLenex::Parser::Objects::RelayPositiondescribing the swimmers ordered within the relay. -
entries– Array ofLenex::Parser::Objects::RelayEntrywith the relay's scheduled starts. -
results– Array ofLenex::Parser::Objects::RelayResultsummarising the relay's outcomes.
The relay entry object exposes:
-
event_id– Required reference to the event contested by the relay team. -
entry_time– Optional entry time string for seeding. -
status– Optional status flag describing the relay entry (EXH,RJC,SICK, orWDR). -
lane– Optional assigned lane number. -
heat_id– Optional reference to the scheduled heat. -
age_group_id– Optional reference to the event age group. -
entry_course– Optional pool length for the entry time. -
entry_distance– Optional entry distance in centimetres for fin-swimming events. -
handicap– Optional relay sport-class override. -
meet_info– OptionalLenex::Parser::Objects::MeetInfodescribing where the qualifying swim occurred. -
relay_positions– Array ofLenex::Parser::Objects::RelayPositionrepresenting the swimmers declared for the entry.
The relay result object exposes:
-
result_id– Required identifier for the relay result within the meet. -
swim_time– Required final relay time string (orNT). -
status– Optional status flag such asDSQ,DNS,DNF,SICK,WDR, orEXH. -
comment– Optional free-text comment (e.g., new record notes). -
event_id– Optional reference to the event contested. -
heat_id– Optional reference to the heat. -
lane– Optional lane number. -
points– Optional points earned for the swim. -
reaction_time– Optional reaction time of the lead-off swimmer. -
handicap– Optional relay sport-class override. -
swim_distance– Optional distance in centimetres for fin-swimming events. -
splits– Array ofLenex::Parser::Objects::Splitobjects for the relay's split times. -
relay_positions– Array ofLenex::Parser::Objects::RelayPositionrepresenting the swimmers who swam the race.
The relay position object exposes:
-
athlete_id– Optional reference to the athlete representing a leg of the relay. -
number– Required leg number (1 for lead-off;-1for alternates). -
reaction_time– Optional reaction or takeover time for the leg. -
status– Optional status flag such asDSQorDNFfor the swimmer. -
athlete– Optional embeddedLenex::Parser::Objects::Athleteused when relay swimmers are inlined (e.g., records). -
meet_info– OptionalLenex::Parser::Objects::MeetInfowith the qualification details for the swimmer.
The official object exposes:
-
official_id– Required identifier unique to the official within the meet. -
first_name– Required first name of the official. -
last_name– Required last name of the official. -
gender– Optional gender marker (MorF). -
grade– Optional certification grade supplied by the federation. -
license– Optional federation-issued license number. -
name_prefix– Optional surname prefix (e.g., "van den"). -
nation– Optional nation code of the official. -
passport– Optional passport identifier. -
contact– OptionalLenex::Parser::Objects::Contactdescribing how to reach the official.
The record list object exposes:
-
course– Required pool length for records in the list. -
gender– Required gender classification for the contained records. -
handicap– Optional handicap classification for para records. -
name– Required human readable list name (e.g., "World Records"). -
nation– Optional federation nation code for the records. -
order– Optional ordering hint when multiple lists appear. -
region– Optional region code for regional record lists. -
type– Optional record type identifier such asWRorER. -
updated– Optional date the record list was last updated. -
age_group– OptionalLenex::Parser::Objects::AgeGroupdescribing the age category covered by the list. -
records– Array ofLenex::Parser::Objects::Recordentries within the list.
The record object exposes:
-
swim_time– Required record time string. -
status– Optional approval status such asAPPROVEDorPENDING. -
comment– Optional free-text comment about the record. -
meet_info– OptionalLenex::Parser::Objects::MeetInfodescribing where the performance occurred. -
swim_style– OptionalLenex::Parser::Objects::SwimStyledescribing the stroke and distance. -
athlete– OptionalLenex::Parser::Objects::RecordAthletewhen the record is held by an individual. -
relay– OptionalLenex::Parser::Objects::RecordRelaywhen the record is held by a relay team. -
splits– Array ofLenex::Parser::Objects::Splitobjects containing available split times.
The record athlete object exposes:
-
athlete_id– Optional identifier supplied when the record references a meet athlete id. -
birthdate– Required birth date of the athlete inYYYY-MM-DDformat. -
first_name/first_name_en– Required first name and optional English variant. -
last_name/last_name_en– Required last name and optional English variant. -
gender– Required gender flag (MorF). -
level– Optional athlete level string. -
license/license_ipc– Optional federation and IPC license identifiers. -
name_prefix– Optional surname prefix (e.g., "van den"). -
nation– Optional nation code. -
passport– Optional passport number. -
status– Optional status flag such asROOKIEorFOREIGNER. -
swrid– Optional SwimRankings.net identifier. -
club– OptionalLenex::Parser::Objects::Clubdescribing the athlete's club when the export provides it.
The record relay object exposes:
-
name– Optional descriptive relay name. -
club– OptionalLenex::Parser::Objects::Clubrepresenting the relay's club affiliation. -
relay_positions– Array ofLenex::Parser::Objects::RecordRelayPositiondescribing the swimmers listed with the record.
The record relay position object exposes:
-
number– Required swimmer order within the relay (1 for the first swimmer). -
reaction_time– Optional reaction or takeover time for the swimmer. -
status– Optional status such asDSQfor the swimmer's leg. -
athlete– RequiredLenex::Parser::Objects::RecordAthletedescribing the swimmer attached to the record.
The time standard list object exposes:
-
time_standard_list_id– Required identifier unique to the time standard list. -
name– Required descriptive label for the list (e.g., "Olympic A"). -
course– Required course designation matching the covered pool length. -
gender– Required gender classification (M,F, orX). -
handicap– Optional handicap classification when the list targets para swimmers. -
type– Optional behaviour flag indicating whether entries must be faster (MAXIMUM), slower (MINIMUM), or use the list as a fallback (DEFAULT). -
age_group– OptionalLenex::Parser::Objects::AgeGroupspecifying the eligible ages. -
time_standards– Array ofLenex::Parser::Objects::TimeStandardentries contained in the list.
The time standard object exposes:
-
swim_time– Required benchmark time string to compare entries against. -
swim_style–Lenex::Parser::Objects::SwimStyledescribing the distance, stroke, and relay composition tied to the standard.
Error handling
Parsing issues raise Lenex::Parser::ParseError. This includes missing required elements or attributes, as well as XML syntax errors encountered while reading the document.
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests.
To run RuboCop:
bundle exec rubocopTo run tests with coverage:
bundle exec rake test:coverageContributing
Bug reports and pull requests are welcome on GitHub at https://github.com/your_username/lenex-parser.
License
The gem is available as open source under the terms of the MIT License.