#!/usr/bin/env python import sys from xml import sax class Block(object): pass class BasicTextBlock(Block): def __init__(self, text = ""): self.text = text def __str__(self): return self.text class Para(BasicTextBlock): def __str__(self): return "\n.PP\n" + self.text.lstrip() class Lpara(BasicTextBlock): def __str__(self): return "\n.IP\n" + self.text.lstrip() class ProgramListing(BasicTextBlock): def __str__(self): return "\n.nf\n%s\n.fi\n" % self.text.lstrip() class ListItem(Block): def __init__(self): self.paras = [] def __str__(self): ret = "" for p in self.paras: ret += str(p) return ret class VariableList(Block): def __init__(self): self.entries = [] def __str__(self): ret = "" for p in self.entries: ret += str(p) return ret class Variable(Block): def __init__(self): self.term = None self.listitem = None def __str__(self): return "\n.TP \n.B %s\n%s\n" % (self.term, str(self.listitem)) class RefSection(Block): def __init__(self, id): self.id = id self.title = None self.elements = [] def first(self, vtype): for o in self.elements: if isinstance(o, vtype): return o return None def last(self, vtype): for o in reversed(self.elements): if isinstance(o, vtype): return o return None def __str__(self): ret = ".SH %s \n" % self.title for p in self.elements: ret += str(p) return ret class DocBookToNroffHandler(sax.ContentHandler): def __init__(self, out=sys.stdout): ########################################################################################### self.out = out self.stack = [] ########################################################################################### self.refentryinfo = {} self.refmeta = {} self.refnamediv = {} self.synopsis = {} self.elementcount = 0 self.formatting = [] self.justformatted = False def is_formatting(self, what): return what in [ "command", "option", "parameter", "replaceable", "filename", "emphasis" ] def translate_formatting(self, what): if what in ["command", "option", "parameter", "filename"]: return "B" elif what in ["emphasis", "replaceable"]: return "I" return "" def startElement(self, name, attrs): ########################################################################################### #print >> self.out, "+" + name name = name.lower() self.stack.append(name) self.elementcount += 1 #print >> self.out, self.stack ########################################################################################### if "refsection" == name: self.refsection = RefSection(attrs["id"]) if "para" == name: if "listitem" in self.stack: self.refsection.last(VariableList).entries[-1].listitem.paras.append(Lpara()) elif "refsection" in self.stack: self.refsection.elements.append(Para()) if "variablelist" == name: self.refsection.elements.append(VariableList()) if "varlistentry" == name: self.refsection.last(VariableList).entries.append(Variable()) if "listitem" == name: self.refsection.last(VariableList).entries[-1].listitem = ListItem() if "programlisting" == name: self.refsection.elements.append(ProgramListing()) if self.is_formatting(name): self.formatting.append(self.translate_formatting(name)) def characters(self, content): ########################################################################################### name = self.stack[-1] #print >> self.out, content ########################################################################################### #TODO this should always use += content instead of = content, in case content is incomplete if "refentryinfo" in self.stack: if "refentrytitle" == name: self.refentryinfo["refentrytitle"] = content if "manvolnum" == name: self.refentryinfo["manvolnum"] = content if "productname" == name: self.refentryinfo["productname"] = content if "date" == name: self.refentryinfo["date"] = content elif "refmeta" in self.stack: if "refentrytitle" == name: self.refmeta["refentrytitle"] = content if "manvolnum" == name: self.refmeta["manvolnum"] = content elif "refnamediv" in self.stack: if "refname" == name: self.refnamediv["refname"] = content if "refpurpose" == name: self.refnamediv["refpurpose"] = content elif "cmdsynopsis" in self.stack: if "command" == name: self.synopsis["command"] = content #don't check more explicitly, take all text content under the arg elif "arg" in self.stack: if not self.synopsis.has_key("args"): self.synopsis["args"] = [] self.synopsis["args"].append(content) elif "refsection" in self.stack: if "title" in self.stack: self.refsection.title = content elif "varlistentry" in self.stack: if "term" == name: self.refsection.last(VariableList).entries[-1].term = content elif "listitem" in self.stack: if "para" in self.stack: self._add_formatted_text(self.refsection.last(VariableList).entries[-1].listitem.paras[-1], content) elif "programlisting" in self.stack: self.refsection.last(ProgramListing).text += content elif "para" in self.stack: self._add_formatted_text(self.refsection.last(Para), content) def _add_formatted_text(self, mypara, content): if self.formatting: mypara.text += "\n.%s %s\n" % ("".join(self.formatting), content) self.justformatted = True else: if self.justformatted: mypara.text += content.lstrip() else: mypara.text += content self.justformatted = False def endElement(self, name): ########################################################################################### #print >> self.out, "-" + name name = name.lower() self.stack.pop() #print >> self.out, self.stack ########################################################################################### if "refentryinfo" == name: print >> self.out, ".TH %(refentrytitle)s %(manvolnum)s \"%(date)s\" \"USER COMMANDS\"" % self.refentryinfo if "refnamediv" == name: print >> self.out, ".SH NAME \n %(refname)s \- %(refpurpose)s" % self.refnamediv if "cmdsynopsis" == name: self.synopsis["argcombo"] = " ".join(self.synopsis["args"]) print >> self.out, ".SH Synopsis \n.B %(command)s \n%(argcombo)s" % self.synopsis if "refsection" == name: print >> self.out, str(self.refsection) if self.is_formatting(name): self.formatting.pop() parser = sax.make_parser() parser.setContentHandler(DocBookToNroffHandler()) parser.parse(open(sys.argv[1], "r"))