9.3. XML 解析

正如我说的,实际解析一个 XML 文档是非常简单的:只要一行代码。从这里出发到哪儿去就是你自己的事了。

例 9.8. 载入一个 XML 文档 (这次是真的)

>>> from xml.dom import minidom                                          
>>> xmldoc = minidom.parse('~/diveintopython/common/py/kgp/binary.xml')  
>>> xmldoc                                                               
<xml.dom.minidom.Document instance at 010BE87C>
>>> print xmldoc.toxml()                                                 
<?xml version="1.0" ?>
<grammar>
<ref id="bit">
  <p>0</p>
  <p>1</p>
</ref>
<ref id="byte">
  <p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\
<xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p>
</ref>
</grammar>
正如在上一节看到的,该语句从 xml.dom 包中导入 minidom 模块。
这就是进行所有工作的一行代码:minidom.parse 接收一个参数并返回 XML 文档解析后的表示形式。这个参数可以是很多东西;在本例中,它只是我本地磁盘上一个 XML 文档的文件名。(你需要将路径改为指向下载的例子所在的目录。) 但是你也可以传入一个文件对象,或甚至是一个类文件对象。这样你就可以在本章后面好好利用这一灵活性了。
minidom.parse 返回的对象是一个 Document 对象,它是 Node 类的一个子对象。这个 Document 对象是联锁的 Python 对象的一个复杂树状结构的根层次,这些 Python 对象完整表示了传给 minidom.parseXML 文档。
toxmlNode 类的一个方法 (因此可以在从 minidom.parse 中得到的 Document 对象上使用)。toxml 打印出了 Node 表示的 XML。对于 Document 节点,这样就会打印出整个 XML 文档。

现在内存中已经有了一个 XML 文档了,你可以开始遍历它了。

例 9.9. 获取子节点

>>> xmldoc.childNodes    
[<DOM Element: grammar at 17538908>]
>>> xmldoc.childNodes[0] 
<DOM Element: grammar at 17538908>
>>> xmldoc.firstChild    
<DOM Element: grammar at 17538908>
每个 Node 都有一个 childNodes 属性,它是一个 Node 对象的列表。一个 Document 只有一个子节点,即 XML 文档的根元素 (在本例中,是 grammar 元素)。
为了得到第一个 (在本例中,时时彩计划软件公式:只有一个) 子节点,只要使用正规的列表语法。回想一下,其实这里没有发生什么特别的;这只是一个由正规 Python 对象构成的正规 Python 列表。
鉴于获取某个节点的第一个子节点是有用而且常见的行为,所以 Node 类有一个 firstChild 属性,它和childNodes[0]具有相同的语义。(还有一个 lastChild 属性,它和childNodes[-1]具有相同的语义。)

例 9.10. toxml 用于任何节点

>>> grammarNode = xmldoc.firstChild
>>> print grammarNode.toxml() 
<grammar>
<ref id="bit">
  <p>0</p>
  <p>1</p>
</ref>
<ref id="byte">
  <p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\
<xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p>
</ref>
</grammar>
由于 toxml 方法是定义在 Node 类中的,所以对任何 XML 节点都是可用的,不仅仅是 Document 元素。

例 9.11. 子节点可以是文本

>>> grammarNode.childNodes                  
[<DOM Text node "\n">, <DOM Element: ref at 17533332>, \
<DOM Text node "\n">, <DOM Element: ref at 17549660>, <DOM Text node "\n">]
>>> print grammarNode.firstChild.toxml()    



>>> print grammarNode.childNodes[1].toxml() 
<ref id="bit">
  <p>0</p>
  <p>1</p>
</ref>
>>> print grammarNode.childNodes[3].toxml() 
<ref id="byte">
  <p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\
<xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p>
</ref>
>>> print grammarNode.lastChild.toxml()     


查看 binary.xml 中的 XML ,你可能会认为 grammar 只有两个子节点,即两个 ref 元素。但是你忘记了一些东西:硬回车!在'<grammar>'之后,第一个'<ref>'之前是一个硬回车,并且这个文本算作 grammar 元素的一个子节点。类似地,在每个'</ref>'之后都有一个硬回车;它们都被当作子节点。所以grammar.childNodes实际上是一个有5个对象的列表:3个 Text 对象和两个 Element 对象。
第一个子节点是一个 Text 对象,它表示在'<grammar>'标记之后、第一个'<ref>'标记之后的硬回车。
第二个子节点是一个 Element 对象,表示了第一个 ref 元素。
第四个子节点是一个 Element 对象,表示了第二个 ref 元素。
最后一个子节点是一个 Text 对象,表示了在'</ref>'结束标记之后、'</grammar>' 结束标记之前的硬回车。

例 9.12. 把文本挖出来

>>> grammarNode
<DOM Element: grammar at 19167148>
>>> refNode = grammarNode.childNodes[1] 
>>> refNode
<DOM Element: ref at 17987740>
>>> refNode.childNodes                  
[<DOM Text node "\n">, <DOM Text node "  ">, <DOM Element: p at 19315844>, \
<DOM Text node "\n">, <DOM Text node "  ">, \
<DOM Element: p at 19462036>, <DOM Text node "\n">]
>>> pNode = refNode.childNodes[2]
>>> pNode
<DOM Element: p at 19315844>
>>> print pNode.toxml()                 
<p>0</p>
>>> pNode.firstChild                    
<DOM Text node "0">
>>> pNode.firstChild.data               
u'0'
正如你在前面的例子中看到的,第一个 ref 元素是 grammarNode.childNodes[1],因为 childNodes[0] 是一个代表硬回车的 Text 节点。
ref 元素有它自己的子节点集合,一个表示硬回车,另一个表示空格,一个表示 p 元素,诸如此类。
你甚至可以在这里使用 toxml 方法,尽管它深深嵌套在文档中。
p 元素只有一个子节点 (在这个例子中无法看出,但是如果你不信,可以看看pNode.childNodes),而且它是表示单字符'0'的一个 Text 节点。
Text 节点的 .data 属性可以向你提供文本节点真正代表的字符串。但是字符串前面的'u'是什么意思呢?答案将自己专门有一部分来论述。
新时时彩对子遗漏 凤凰时时彩软件下载 时时彩直选 玩时时彩犯法吗 新疆时时彩手机软件
时时彩规则上全狐网 时时彩三星组选缩水 时时彩开奖号码时时彩 银航国际时时彩还开吗 江西时时彩官网询问
重庆时时彩官网手机版 时时彩怎么找漏洞 360江西时时彩走势图表 内蒙古11选5推荐号码 江西时时彩后一冷
时时彩玩法皇恩娱乐 时时彩计划网站哪个好 重庆时时彩定位胆个位技巧 时时彩实战攻略 时时彩网银狐娱乐
百家乐平注常赢玩法 三公游戏单机版 圣王txt全集下载 玩北京赛车那个平台好 江西多乐彩11选5软件下载
江苏十一选五开奖结果彩控 「百家乐」赢钱诀窍 中国体彩 上海快3遗漏 快乐扑克3豹子走势图
排列七中奖规则 北京时时彩官网 重庆时时彩开奖助手 新疆时时彩 福彩3d开奖结果
北京快3-开奖结果 内蒙古时时彩开奖结果查询 赌博默示录下载 快乐10分开奖直播 河北快3遗漏