import sys
import xml.etree.ElementTree as ET
def parse_time(t):
h, m, s = t.split(":")
return int(h) * 3600 + int(m) * 60 + float(s)
def text(el, path, default=""):
node = el.find(path)
return node.text.strip() if node is not None and node.text else default
def parse_chapter_display(chapter_atom):
displays = chapter_atom.findall("ChapterDisplay")
out = []
for d in displays:
lang = text(d, "ChapterLanguage", "")
ietf = text(d, "ChapLanguageIETF", "")
string = text(d, "ChapterString", "")
out.append(f"{ietf}:{string}" if ietf else f"{lang}:{string}")
return " | ".join(out)
def main(xml_file):
tree = ET.parse(xml_file)
root = tree.getroot()
editions = root.findall("EditionEntry")
for ed in editions:
edition_uid = text(ed, "EditionUID", "unknown")
rows = []
for ch in ed.findall("ChapterAtom"):
row = {
"start": parse_time(text(ch, "ChapterTimeStart", "0:00:00.000")),
"enabled": text(ch, "ChapterFlagEnabled", ""),
"hidden": text(ch, "ChapterFlagHidden", ""),
"title": parse_chapter_display(ch)
}
rows.append(row)
rows.sort(key=lambda r: r["start"])
out_file = f"chapters.ed{edition_uid}.tsv"
with open(out_file, "w", encoding="utf-8") as f:
headers = ["start", "enabled", "hidden", "title"]
f.write("\t".join(headers) + "\n")
for r in rows:
f.write(
f"{r['start']}\t{r['enabled']}\t{r['hidden']}\t{r['title']}\n"
)
print(f"Wrote {out_file}")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: chapters_to_tsv.py chapters.xml")
sys.exit(1)
main(sys.argv[1])