10.7. 整合所有内容

您已经学习了很多内容。让我们回顾一下,看看所有部分是如何组合在一起的。

首先,这是一个使用 getopt 模块从命令行获取参数的脚本。


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

您创建了一个新的 KantGenerator 类实例,并将语法文件和可能在命令行中指定的源传递给它。

    k = KantGenerator(grammar, source)

KantGenerator 实例会自动加载语法文件,该文件是一个 XML 文件。您使用自定义的 openAnything 函数打开文件(该文件可以存储在本地文件或远程 Web 服务器中),然后使用内置的 minidom 解析函数XML 解析成 Python 对象树

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

哦,在此过程中,您利用了对 XML 文档结构的了解,设置了一个小的引用缓存,这些引用只是 XML 文档中的元素。

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

如果您在命令行中指定了一些源材料,则使用它;否则,您将遍历语法,查找“顶级”引用(未被任何其他内容引用),并将其用作起点。

    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)

现在您要遍历源材料。源材料也是 XML,您需要逐个节点地解析它。为了保持代码分离和更易于维护,您为每种节点类型使用单独的处理程序

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

您在语法中跳转,解析每个 p 元素的所有子元素

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

choice 元素替换为随机子元素,

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

并将 xref 元素替换为相应 ref 元素(您之前缓存的)的随机子元素。

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

最终,您将解析为纯文本,

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

然后将其打印出来。


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