14. 处理 XML 文档
![]() |
请看以下 XML 文档:
<tribu>
<enseignant>
<personne sexe="M">
<nom>dupont</nom>
<prenom>jean</prenom>
<age>28</age>
ceci est un commentaire
</personne>
<section>27</section>
</enseignant>
<etudiant>
<personne sexe="F">
<nom>martin</nom>
<prenom>charline</prenom>
<age>22</age>
</personne>
<formation>dess IAIE</formation>
</etudiant>
</tribu>
我们分析此文档以生成以下控制台输出:
tribu
enseignant
(personne,(sexe,M) )
nom
[dupont]
/nom
prenom
[jean]
/prenom
age
[28]
/age
/personne
section
[27]
/section
/enseignant
etudiant
(personne,(sexe,F) )
nom
[martin]
/nom
prenom
[charline]
/prenom
age
[22]
/age
/personne
formation
[dess IAIE]
/formation
/etudiant
/tribu
我们需要知道如何识别:
- 起始标签,例如 <training>;
- 结束标签,例如 </teacher>;
- 带有属性的起始标签,例如 <person gender="F">;
- 标签的正文,例如 <name>martin</name> 中的 "martin"。
解析 XML 代码的程序称为 XML 解析器。有两个模块提供了解析 XML 代码所需的功能:xml.sax 和 xml.sax.handler。
[xml.sax] 模块通过以下语句为我们提供了一个 XML 解析器:
该解析器按顺序解析 XML 文本。它在事件发生时调用用户定义的方法:
- 在开始标签上调用 startElement 方法;
- 在结束标签上调用 endElement 方法;
- 在标签主体上调用 characters 方法。
我们需要告诉解析器哪个类实现了这些方法:
我们将一个实现了 startElement、endElement 和 characters 方法的类实例传递给解析器的 setContentHandler 方法。所使用的类是 xml.sax.handler.ContentHandler 类的子类。上述方法的调用会带参数:
- name 是起始标签的名称。attributes 是该标签属性的字典。因此,对于标签 <person sex="M">,我们将有 name="person" 和 attributes={'sex':'M'}
- name 是结束标签的名称。因此,对于 </student> 标签,我们将得到 name='student'。
- data 是标签的正文内容。因此,如果标签是
我们将得到 data='\r\n dupont\r\n '。通常,我们会去除数据前后多余的空格。
既然已经说明了这一点,我们可以继续讲解解析 XML 文档的脚本:
该程序(xml_sax_01)
注:
- 该脚本使用了来自 xml.sax 和 xml.sax.handler 模块的函数库(第 3 行);
- 第 62 行:已解析的 XML 文件;
- 第 68 行:XML 解析器;
- 第 70 行:解析器发出的事件的处理程序将是一个 XmlHandler 类的实例;
- 第 72 行:开始解析 XML 文档;
- 第 6 行:实现 startElement、endElement 和 characters 方法的类。它继承自 xml.sax.handler.ContentHandler 类,该类实现了解析器所使用的方法;
- 第 9 行:startElement 方法;
- 第 30 行:endElement 方法;
- 第 41 行:characters 方法。
结果即本段开头所示。
