Zanurkuj w Pythonie/Skrypty i strumienie - wszystko razem

Wszystko razem edytuj

Przemierzyliśmy kawał drogi. Zatrzymajmy się na chwilę i zobaczmy jak te wszystkie elementy do siebie pasują. Zaczniemy od skryptu, który pobiera argumenty z linii poleceń używając modułu getopt.

def main(argv):
# ...
    try:
        opts, args = getopt.getopt(argv, "hg:d", ["help", "grammar="])
    except getopt.GetoptError:
# ...
    for opt, arg in opts:
# ...

Tworzymy nową instancję klasy KantGenerator i przekazujemy jej plik z gramatyką oraz źródło, które może być, ale nie musi, podane w linii poleceń.

k = KantGenerator(grammar, source)

Instancja klasy KantGenerator automatycznie wczytuje gramatykę, która jest plikiem XML. Wykorzystujemy naszą funkcję openAnything do otwarcia pliku (który może być ulokowany lokalnie lub na zdalnym serwerze), następnie używamy wbudowanego zestawu funkcji parsujących minidom do sparsowania XML-a do postaci drzewa obiektów Pythona.

def _load(self, source):
    sock = toolbox.openAnything(source)
    xmldoc = minidom.parse(sock).documentElement
    sock.close()

Ach i po drodze wykorzystujemy naszą wiedzę o strukturze dokumentu XML do utworzenia małego bufora referencji, którymi są po prostu elementy dokumentu XML.

def loadGrammar(self, grammar):
    for ref in self.grammar.getElementsByTagName("ref"):
        self.refs[ref.attributes["id"].value] = ref

Jeśli został podany jakiś materiał źródłowy w linii poleceń, używamy go. W przeciwnym razie na podstawie gramatyki wyszukujemy referencję na najwyższym poziomie (tą do której nie mają odnośników żadne inne elementy) i używamy jej jako punktu startowego.

def getDefaultSource(self):
    xrefs = {}
    for xref in self.grammar.getElementsByTagName("xref"):
    xrefs[xref.attributes["id"].value] = 1
    xrefs = xrefs.keys()
    standaloneXrefs = [e for e in self.refs.keys() if e not in xrefs]
    return '<xref id="%s"/>' % random.choice(standaloneXrefs)

Teraz przedzieramy się przez materiał źródłowy. Ten materiał to także XML i parsujemy go węzeł po węźle. Aby podzielić nieco kod i uczynić go łatwiejszym w utrzymaniu, używamy oddzielnych funkcji obsługi (ang. handlers) dla każdego typu węzła.

def parse_Element(self, node):
    handlerMethod = getattr(self, "do_%s" % node.tagName)
    handlerMethod(node)

Przelatujemy przez gramatykę, parsując wszystkie elementy potomne każdego elementu p,

def do_p(self, node):
# ...
    if doit:
        for child in node.childNodes: self.parse(child)

zastępując elementy choice losowym elementem potomnym,

def do_choice(self, node):
    self.parse(self.randomChildElement(node))

i zastępując elementy xref losowym elementem potomnym odpowiedniego elementu ref, który wcześniej został zachowany w buforze.

def do_xref(self, node):
    id = node.attributes["id"].value
    self.parse(self.randomChildElement(self.refs[id]))

W końcu parsujemy wszystko do zwykłego tekstu,

def parse_Text(self, node):
    text = node.data
# ...
    self.pieces.append(text)

który wypisujemy.

def main(argv):
# ...
    k = KantGenerator(grammar, source)
    print k.output()