Introduction

Generating schemas (RNG) and documentation (HTML) from TEI (Text Encoding Initiative) ODD (One Document Does it all) files is an important process in TEI projects. This article analyzes how the TEI Garage API, used internally by Roma (the TEI ODD editor), works and introduces how to call the API directly from scripts to convert ODD files.

What Is TEI Garage?

TEI Garage is a web service provided by the TEI community that can perform conversions between various formats. For ODD file processing in particular, it provides the following features:

  • ODD to Compiled ODD conversion
  • Compiled ODD to RELAX NG schema conversion
  • ODD to HTML document conversion
  • Many other format conversions

Analyzing Roma’s Internal Behavior

By observing Roma’s network traffic, we found that it uses the following conversion chains:

For HTML Document Generation

ODD → ODDC (Compiled ODD) → TEI → xHTML

Actual API endpoint:

https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml/conversion

For RNG Schema Generation

ODD → ODDC (Compiled ODD) → RELAXNG

Actual API endpoint:

https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/relaxng%3Aapplication%3Axml-relaxng/conversion

Conversion Parameter Details

Roma sends properties in the following XML format during conversion:

conversions>
  conversion index="0">
    property id="oxgarage.getImages">falseproperty>
    property id="oxgarage.getOnlineImages">falseproperty>
    property id="oxgarage.lang">japroperty>
    property id="oxgarage.textOnly">falseproperty>
    property id="pl.psnc.dl.ege.tei.profileNames">defaultproperty>
  conversion>
  conversion index="1">
    property id="oxgarage.getImages">falseproperty>
    property id="oxgarage.getOnlineImages">falseproperty>
    property id="oxgarage.lang">japroperty>
    property id="oxgarage.textOnly">trueproperty>
    property id="pl.psnc.dl.ege.tei.profileNames">defaultproperty>
  conversion>
conversions>

Meaning of each property:

  • oxgarage.getImages: Whether to include images
  • oxgarage.getOnlineImages: Whether to fetch online images
  • oxgarage.lang: Output language (ja=Japanese, en=English)
  • oxgarage.textOnly: Whether to output text only (recommended to set to true for RNG generation)
  • pl.psnc.dl.ege.tei.profileNames: Profile to use (usually default)

Implementation: Automated Conversion with a Bash Script

The following is a Bash script that converts ODD files using the TEI Garage API:

#!/bin/bash

# ODD conversion script using the TEI Garage API
# Usage: ./convert-odd.sh
# output-type: html or rng

ODD_FILE="$1"
OUTPUT_TYPE="$2"

if [ -z "$ODD_FILE" ] || [ -z "$OUTPUT_TYPE" ]; then
    echo "Usage: $0  "
    echo "  output-type: html or rng"
    exit 1
fi

BASE_NAME=$(basename "$ODD_FILE" .odd)
DIR_NAME=$(dirname "$ODD_FILE")

# HTML conversion
if [ "$OUTPUT_TYPE" = "html" ]; then
    echo "Converting ODD to HTML documentation..."

    # Conversion properties (for HTML)
    PROPERTIES='falsefalsejafalsedefaultfalsefalsejafalsedefault'

    # API endpoint (ODD → ODDC → TEI → xHTML)
    API_URL="https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml/conversion"

    # Upload file and convert with cURL
    curl -s -o "${DIR_NAME}/${BASE_NAME}.html" \
        -F upload=@"$ODD_FILE" \
        "${API_URL}?properties=${PROPERTIES}"

    echo "HTML documentation saved to ${DIR_NAME}/${BASE_NAME}.html"

# RNG conversion
elif [ "$OUTPUT_TYPE" = "rng" ]; then
    echo "Converting ODD to RNG schema..."

    # Conversion properties (for RNG - textOnly set to true)
    PROPERTIES='falsefalsejatruedefaultfalsefalsejatruedefault'

    # API endpoint (ODD → ODDC → RELAXNG)
    API_URL="https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/relaxng%3Aapplication%3Axml-relaxng/conversion"

    # Upload file and convert with cURL
    curl -s -o "${DIR_NAME}/${BASE_NAME}.rng" \
        -F upload=@"$ODD_FILE" \
        "${API_URL}?properties=${PROPERTIES}"

    echo "RNG schema saved to ${DIR_NAME}/${BASE_NAME}.rng"
fi

Python Implementation Example

For more flexible processing, Python can also be used:

#!/usr/bin/env python3

import sys
import requests
from pathlib import Path
from urllib.parse import quote

def convert_odd(odd_file, output_type='html'):
    """
    Convert an ODD file using the TEI Garage API

    Args:
        odd_file: Path to the ODD file
        output_type: 'html' or 'rng'
    """

    # Prepare conversion properties in XML format
    text_only = 'true' if output_type == 'rng' else 'false'
    properties = f'''

            false
            false
            ja
            {text_only}
            default


            false
            false
            ja
            {text_only}
            default

    '''

    # Set the API endpoint
    if output_type == 'html':
        endpoint = 'ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml'
        ext = '.html'
    else:  # rng
        endpoint = 'ODD%3Atext%3Axml/ODDC%3Atext%3Axml/relaxng%3Aapplication%3Axml-relaxng'
        ext = '.rng'

    api_url = f'https://teigarage.tei-c.org/ege-webservice/Conversions/{endpoint}/conversion'

    # Upload file and convert
    with open(odd_file, 'rb') as f:
        files = {'upload': f}
        params = {'properties': properties}

        print(f"Converting {odd_file} to {output_type.upper()}...")
        response = requests.post(api_url, files=files, params=params)

        if response.status_code == 200:
            # Save the output file
            output_file = Path(odd_file).with_suffix(ext)
            output_file.write_bytes(response.content)
            print(f"Successfully saved to {output_file}")
            return output_file
        else:
            print(f"Error: {response.status_code}")
            print(response.text)
            return None

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python convert_odd.py  ")
        print("  output-type: html or rng")
        sys.exit(1)

    odd_file = sys.argv[1]
    output_type = sys.argv[2]

    if output_type not in ['html', 'rng']:
        print("Output type must be 'html' or 'rng'")
        sys.exit(1)

    convert_odd(odd_file, output_type)

Error Handling and Notes

1. Validating API Responses

When conversion fails, TEI Garage may return an HTML error page. Always validate the response:

# Error checking example
if grep -q "HTTP Status" "${OUTPUT_FILE}"; then
    echo "Error occurred during conversion"
    cat "${OUTPUT_FILE}"
    exit 1
fi

2. File Size Limitations

The TEI Garage API has upload file size limitations (typically a few MB). For large ODD files, consider using local conversion tools (such as Saxon-HE).

3. Network Timeouts

Since conversion processing can take time, appropriate timeout settings are needed:

# cURL timeout setting example
curl --max-time 300 -s -o output.html ...

Batch Conversion of Multiple Files

A script example for batch-converting multiple ODD files:

#!/bin/bash

# Convert all ODD files
for odd_file in *.odd; do
    echo "Processing $odd_file..."

    # Generate both HTML and RNG
    ./convert-odd.sh "$odd_file" html
    ./convert-odd.sh "$odd_file" rng

    echo "Completed $odd_file"
    echo "---"
done

API Endpoint URL Structure

TEI Garage API endpoints have the following structure:

https://teigarage.tei-c.org/ege-webservice/Conversions/{input-format}/{intermediate-format1}/{intermediate-format2}/{output-format}/conversion

Each part is specified in URL-encoded format:

  • ODD%3Atext%3Axml = ODD:text:xml
  • ODDC%3Atext%3Axml = ODDC:text:xml (Compiled ODD)
  • TEI%3Atext%3Axml = TEI:text:xml
  • xhtml%3Aapplication%3Axhtml%2Bxml = xhtml:application:xhtml+xml
  • relaxng%3Aapplication%3Axml-relaxng = relaxng:application:xml-relaxng

Other Conversion Options

TEI Garage supports various other conversions:

ODD to XSD (XML Schema)

API_URL="https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/xsd%3Aapplication%3Axml-xsd/conversion"

ODD to DTD

API_URL="https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/dtd%3Aapplication%3Axml-dtd/conversion"

ODD to Schematron

API_URL="https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/sch%3Atext%3Axml/conversion"

Summary

By using the TEI Garage API directly, ODD file conversion can be automated without going through Roma. The benefits of this approach:

  1. Automation: Can be integrated into CI/CD pipelines
  2. Batch processing: Easy batch conversion of multiple files
  3. Customization: Fine-grained control over conversion parameters
  4. Language-independent: Can be executed anywhere curl is available

In particular, by combining version control of ODD files with automated builds, you can build an efficient development workflow while maintaining consistency between schemas and documentation.

References