🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 10.7. 全部放在一起 你已经了解很多基础的东西。让我们回来看看所有片段是如何整合到一起的。 作为开始,这里是一个[接收命令行参数](command_line_arguments.html "10.6. 处理命令行参数")的脚本,它使用 `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` 函数打开这个文件 ([可能保存在一个本地文件中或者一个远程服务器上](index.html#kgp.openanything "10.1. 抽象输入源")),然后使用内置的 `minidom` 解析函数[将 XML 解析为一棵 Python 对象树](../xml_processing/parsing_xml.html "9.3. XML 解析")。 ``` def _load(self, source): sock = toolbox.openAnything(source) xmldoc = minidom.parse(sock).documentElement sock.close() ``` 哦,根据这种方式,你将使用到 XML 文档结构的知识[建立一个引用的小缓冲](caching.html "10.3. 查询缓冲节点"),这些引用都只是 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,你每次解析一个节点。为了让代码分离并具备更高的可维护性,你可以使用[针对每个节点类型的独立处理方法](handlers_by_node_type.html "10.5. 根据节点类型创建不同的处理器")。 ``` def parse_Element(self, node): handlerMethod = getattr(self, "do_%s" % node.tagName) handlerMethod(node) ``` 你在语法里面跳来跳去,解析每一个 `p` 元素的[所有孩子](child_nodes.html "10.4. 查找节点的直接子节点"), ``` 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)) ``` 并用对应 `ref` 元素的任意孩子替换 `xref`,前面你已经进行了缓冲。 ``` 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() ```