xmltv 2.1.0

XMLTV for electronic program guide (EPG) parser and generator using serde.
Documentation

xmltv

A high-performance Rust library and CLI tool for parsing, filtering, and generating XMLTV Electronic Program Guide (EPG) files. It leverages serde for robust serialization and deserialization of the XMLTV standard.

Features

xmltv library

It is minimalistic, it contains XMLTV struct so you can use them through serde and some utility functions.

It also flatten some elements like <new/> to be a boolean in order to avoid boilerplate.

CLI

  • Fast Parsing: Efficiently handles large XMLTV files using quick-xml.
  • Flexible Filtering: Filter by channel IDs, time slots (with day-of-week support), and keyword searches.
  • Data Minimization: Remove heavy elements like credits, icons, or descriptions to reduce file size.
  • Multi-Format Export: Convert XMLTV to JSON, iCal (ICS), Atom Feed, or JSON Feed.
  • Timezone Aware: Shift or normalize timestamps to UTC or local time.
  • Deteriministic IDs: Generates stable UUID v8 identifiers for programs based on content hashing.

Installation

# Clone and build the CLI
cargo build --release

Usage

Command line interface (CLI)

The CLI allows you to process EPG data from local files or multiple merged sources.

Install it with cargo install xmltv or with the binaries.

Options

  • -c <CHANNEL LIST> or --channels=<CHANNEL LIST>: channels you want to keep, ie: -c tf1,m6,Arte. You can also check them with the TUI using -c ?
  • --cleanse <ITEM LIST>: items you want to remove form the XMLTV file. I made this option because, in XMLTV file there are a lot of data and we don't need all of them and we may want to reduce the size of the file. Available items are:
    • credits: remove all credits. If you want to remove some of them, use:
      • directors
      • actors
      • writers
      • adapters
      • producers
      • composers
      • editors
      • presenters
      • commentators
      • guests
    • categories
    • new
    • countries
    • keywords
    • sub-titles
    • languages
    • videos
    • audios
    • subtitles
    • last-chances
    • descriptions
    • dates
    • origin-languages
    • length
    • premieres
    • previously-showns
    • ratings
    • star-ratings
    • reviews
    • images
    • episode-nums
    • icons
    • urls
  • -d NUMBER or --days NUMBER: number of days in the EPG to keep (from today)
  • -l <FILE> or --load <FILE>: load configuration from a JSON file
  • -m <FILE> or --merge <FILE>: merge another XMLTV file (can be used multiple times to merge several files)
  • -s <QUERY> or --search <QUERY>: search programmes by title (case-insensitive)
  • -t <TZ> or --timezone <TZ>: output timezone for programme times. Values: utc (default), local (system timezone), or offset like +0100
  • -f <FORMAT> or --format <FORMAT>: output format: xml (default), json, ical, atom, jsonfeed
  • --epg: display the EPG in a terminal UI

Example

Basic Filtering and Conversion

# Convert XMLTV to JSON for the next 3 days, keeping only specific channels
xmltv input.xml --format json --days 3 --channels "TF1.fr,M6.fr,Arte.tv"

Advanced Time Slots: filter programs based on when you actually watch TV.

# Keep programs on weekdays from 6 PM to 11 PM and all day on weekends
xmltv input.xml --time-slots "Mon-Fri 18:00-23:00" "Sat,Sun 00:00-23:59"

Merging and Cleaning

# Merge two sources and remove heavy metadata to save space
xmltv main.xml --merge secondary.xml --cleanse "credits,images,episode-nums"

Creating Calendar Reminders

# Search for "Football" and export as an iCal file
xmltv input.xml --search "Football" --format ical > sports.ics

Library

use std::str::FromStr;

use quick_xml::de::from_str;
use quick_xml::se::to_string_with_root;
use xmltv::*;

fn main() {
    let xml = "<tv>\
<programme channel=\"1\" start=\"2021-10-09 12:00:00 +0200\" stop=\"2021-10-09 13:00:00 +0200\">\
<title>Les feux de l&apos;amour é</title>\
</programme>\
<programme channel=\"2\" start=\"2021-10-09 12:20:00 +0200\" stop=\"2021-10-09 12:35:00 +0200\">\
<title lang=\"fr-FR\">Le journal</title>\
</programme>\
<programme channel=\"3\" start=\"2021-10-09 13:00:00 +0200\" stop=\"2021-10-09 13:40:00 +0200\">\
<title>Le journal</title>\
</programme>\
</tv>";

    // deserialize into the root object (Tv)
    let item: Tv = from_str(xml).unwrap();

    // serialize into string
    let _out = to_string_with_root("tv", &tv).unwrap();
}

To serialize big files, you can look into tests/from_files.rs::test_programmes_from_files. It reads programmes one by one without loading everything in RAM.

Ressources

XMLTV DTD is here: https://github.com/XMLTV/xmltv/blob/master/xmltv.dtd