ArcGIS Python编程案例(14)-五个常用Python处理任务

附录A 自动执行Python脚本 |||


我们将在本章介绍以下案例:

  • 从分隔符文本文件中读取数据
  • 发送电子邮件
  • 访问FTP服务器中的文件
  • 创建ZIP文件
  • 读取XML文件

引言

在本章中,你将学习如何编写Python脚本来执行常用的处理任务。这些任务包括读写分隔符文本文件,发送电子邮件,与FTP服务器交互操作,创建.zip文件以及读写JSON和XML文件。GIS程序员应当了解如何在Python脚本来完成这些功能。

从分隔符文本文件中读取数据

对于GIS程序员来说使用Python处理文件是非常重要的环节。文本文件经常作为不同系统之间的数据交换格式。文本文件简单,跨平台并且易于处理。逗号分隔符文本文件和制表符分隔符文本文件是最为常用的形式。对于GIS程序员来说读取包含X,Y坐标以及其他属性信息的逗号分隔符文本文件是一类常见的处理任务。这些读取后信息再转换成像shapefile或地理数据库的GIS数据格式。

Getting ready

使用Python的文件处理功能前,你必须首先打开文件。文件打开后,文件中的数据就可以通过Python提供的功能进行处理,最后关闭文件。处理完成后要记得关闭文件。
在本案例中,你将学习如何对一个逗号分隔符文本文件执行打开,读取,处理并关闭操作。

How to do it...

按照以下步骤创建Python脚本来读取逗号分隔符文本文件:
1.在C:\ArcpyBook\data文件夹中找到一个N_America.A2007275.txt的文件。用文本编辑器打开该文件,你会看到如下内容:

18.102,-94.353,310.7,1.3,1.1,10/02/2007,0420,T,72
19.300,-89.925,313.6,1.1,1.0,10/02/2007,0420,T,82
19.310,-89.927,309.9,1.1,1.0,10/02/2007,0420,T,68
26.888,-101.421,307.3,2.7,1.6,10/02/2007,0425,T,53
26.879,-101.425,306.4,2.7,1.6,10/02/2007,0425,T,45
36.915,-97.132,342.4,1.0,1.0,10/02/2007,0425,T,100
................

该文件包含的火情数据是从2007年10月02日当天卫星遥感影像判断获取。每行数据包含了经纬度信息以及其他相关信息,比如日期和时间,卫星类型,可信度等等。在本案例中,你将提取出纬度,经度和可信度信息。
2.打开IDLE,创建一个脚本文件并保存为
C:\ArcpyBook\Appendix2\ReadDelimitedTextFile.py文件。
3.调用Pyhon的open()函数来打开要读取的文件:

f = open("C:/ArcpyBook/data/N_America.A2007275.txt","r")

4.读取文本文件中的内容并写入到列表中:

lstFires = f.readlines()

5.添加一个for循环语句来迭代遍历lstFires变量中的所有行:

for fire in lstFires:

6.调用split()函数并使用逗号作为分隔符,将分离后的值保存到列表中,然后赋值给变量lstValues。保证语句的缩进使其位于for语句中:

lstValues = fire.split(",")

7.使用索引值来获取纬度,经度和可信度,并分别创建新的变量:

latitude = float(lstValues[0])
longitude = float(lstValues[1])
confid = int(lstValues[8])

8.使用print语句打印所有值:

print "The latitude is: " + str(latitude) + " The longtitude is " + str(longtitude) + "The confidence value is " + str(confid)

9.关闭文件:

f.close()

10.完整代码如下:

f = open("C:/ArcpyBook/data/N_America.A2007275.txt","r")
lstFires = f.readlines()
for fire in lstFires:
    lstValues = fire.split(",")
    latitude = float(lstValues[0])
    longitude = float(lstValues[1])
    confid = int(lstValues[8])
    print  "The latitude is: " + str(latitude) + " The longtitude is " + str(longtitude) + "The confidence value is " + str(confid)
f.close()

11.保存并运行脚本。你将看到如下结果显示:

The latitude is: 18.102 The longitude is: -94.353 The confidence  value is: 72 
The latitude is: 19.3 The longitude is: -89.925 The confidence  value is: 82 
The latitude is: 19.31 The longitude is: -89.927 The confidence  value is: 68
The latitude is: 26.888 The longitude is: -101.421 The confidence  value is: 53 
The latitude is: 26.879 The longitude is: -101.425 The confidence  value is: 45 
The latitude is: 36.915 The longitude is: -97.132 The confidence  value is: 100
...................
The latitude is: 54.19 The longitude is: -122.502 The confidence  value is: 92
How it works...

Python中open()函数创建一个文件对象,该对象引用一个链接地址来指向计算机中的文件。open()函数中的第一个参数是你想要打开文件的路径。第二个参数指定一种模式,该模式通常是只读(r),写入(w)或添加(a)。r模式表明你打开文件进行只读操作,而w模式则表明你打开文件要进行写入操作。如果你以写入模式打开的文件已存在,那么Python就会覆盖掉该文件中已有数据,因此使用该模式应当注意。添加模式(a)则会打开文件进行写入操作,但是不会覆盖已有数据,而是在文件末尾添加写入的数据。在本案例中,我们以只读模式打开N_America.A2007275.txt文件。
readlines()函数会读取整个文件内容并写入一个Python列表中。该列表保存到变量lstFires。文本文件中的每一行数据是列表中的一个元素。由于该函数会读取整个文件到列表中,因此调用该方法时需要注意,一个大文件会显著影响性能。
for循环语句用于迭代遍历lstFires中的每一个值,在该语句中的split()函数用于从以某种分隔符分隔文本行中创建一个列表对象。本案例中的文件是以逗号作为分隔符,因此我们可以调用split(",")语句。你还可以使用其他像制表符,空格或其他分隔符来分割文本。split()函数创建的列表对象保存在lstValues变量中。该变量包含了每一个火情数据。如下图所示。你会看到纬度数据占据第一个位置,经度数据占据第二个数据。列表从零值开始索引:

使用索引值(分别引用纬度,经度和可信度),我们创建了latitudelongitude以及confid三个新变量。最后,我们打印输出每一个值。我们可以调用插入游标(InsertCursor)对象将这些信息写入到一个要素类中。

There's more...

同读取文件一样,你还可以向文件中写入数据。write()函数可用于将列表结构的内容写入到一个文件中。写入数据之前,你需要先以写入或添加模式打开文件。

发送电子邮件

有时候,你可能需要编写Python脚本来发送电子邮件。举个例子,在一个长时间运行的地理处理操作中需要提醒操作成功完成或出现错误,在类似情况下,发送电子邮件就很有用处。

Getting ready

通过Python脚本发送电子邮件需要脚本运行的机器能够访问邮箱服务器,可以是一个Yahoo,Gmail之类的公共的电子邮件服务,这也可以使用像Outlook的应用程序配置的发送邮件服务器。不论哪种方式,你都需要知道电子邮箱服务器的域名和端口。Python的smtplib模块用于创建邮箱服务器的连接并发送电子邮件。
Python的email模块包含一个Message类用来表达电子邮件信息。每一条消息包含消息头和消息体。该类不能用于发送电子邮件,只是处理消息对象的表达。Message类通过调用message_from_file()message_from_string()函数分别解析包含在电子邮件中的文件和字符串。两个函数都会创建一个新的Message对象。邮件体可以通过调用Message.get_payload()方法获取。
在本案例中,你将学习如何在Python脚本中使用smtp类来发送包含附件内容的电子邮件。

原书采用Gmail邮箱服务,由于网络原因,我们在案例中改为使用网易126邮箱服务。如果你已经拥有了一个126账号,那么只要提供你的用户名和密码就可以。如果你还没有126账号,你需要注册一个或者使用其他邮件服务来完成本练习;126邮箱账号是免费的。

How to do it...

按照以下步骤来创建能够发送电子邮件的脚本:
1.打开IDLE,创建一个脚本并保存为C:\ArcpyBook\Appendix2\SendEmail.py
2.为了能够在发送带附件的电子邮件,你需要导入os模块,smtplib模块以及email模块中多个类。如下所示:

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os

3.创建下面的几个变量并分别保存你的Gmail用户名和密码。

##<用户名>替换为你的邮箱账号
gmail_user = "<用户名>"
##<密码>替换为你的邮箱账号密码
gmail_pwd= "<密码>"

4.定义一个mail()函数。该函数将接受四个参数:tosubjecttext以及attach。每一个参数的意义不言而喻。创建一个新的MIMEMultipart对象并分别赋值给fromtosubject键值。你还可以对新创建的对象调用MIMEMultipart.attach()方法来给邮件添加一个文本附件:

def mail(to,subject,text,attach):
    msg = MIMEMultipart()
    msg['From'] = gmail_user
    msg['To'] = to
    msg['Subject'] = subject
    msg.attach(MIMEText(text))

5.在邮件中添加附件:

part = MIMEBase("application","octet-stream")
part.set_payload(open(attach,"rb").read())
Encoders.encode_base64(part)
part.add_header("Content-Dispositon","attachment;filename='%s'" % os.path.basename(attach))
msg.attach(part)

6.创建一个新的SMTP对象引用谷歌Gamil服务,传递用户名和密码来连接该邮件服务,发送邮件最后关闭连接:

mailServer = smtplib.SMTP("smtp.126.com")
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmail_user,gmail_pwd)
mailServer.sendmail(gmail_user,to,msg.as_string())
mailServer.quit()

7.调用mail()函数,传递收件人,邮件主题,邮件的内容以及附件参数:

##<收件人地址>替换为发件人邮箱地址
mail("<收件人地址>","Hello from python!","This is an email sent with python","C:/ArcpyBook/data/bc_pop1996.csv")

8.完整代码如下:

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os
##<用户名>替换为你的邮箱账号
gmail_user = "<用户名>"
##<密码>替换为你的邮箱账号密码
gmail_pwd= "<密码>"
def mail(to,subject,text,attach):
    msg = MIMEMultipart()
    msg['From'] = gmail_user
    msg['To'] = to
    msg['Subject'] = subject
    msg.attach(MIMEText(text))
    part = MIMEBase("application","octet-stream")
    part.set_payload(open(attach,"rb").read())
    Encoders.encode_base64(part)
    part.add_header("Content-Disposition","attachment;filename='%s'" % os.path.basename(attach))
    msg.attach(part)
    mailServer = smtplib.SMTP("smtp.126.com")
    mailServer.ehlo()
    mailServer.starttls()
    mailServer.ehlo()
    mailServer.login(gmail_user,gmail_pwd)
    mailServer.sendmail(gmail_user,to,msg.as_string())
    mailServer.quit()
    print "Send Successfully!"
##<收件人地址>替换为发件人邮箱地址
mail("<收件人地址>","Hello from python!","This is an email sent with python","C:/ArcpyBook/data/bc_pop1996.csv")

9.保存并运行脚本。指定某个邮箱账号作为收件人。

How it works...

mail()函数接受的第一个参数是接收邮件的电子邮箱地址。该地址可以是任何合法的电子邮箱地址,不过需要提供一个可以查看的邮箱账号,这样你才可以确认脚本是否正确执行。第二个参数是邮件的主题。第三个参数是邮件内容。最后一个参数是附件的名称。在这里将bc_pop1996.csv文件作为附件。你还可以使用任何你能够获取的文件。
随后我们在mail()函数中创建了一个新的MIMEMultipart对象,并分别赋给fromtosubject键值。你还可以调用MIMEMultipart.attach()方法将邮件内容附加到msg对象中。随后通过调用msg.attach(part)语句将bc_pop1996.csv文件作为附件添加到使用MIMEBase对象创建的邮件中。
到目前为止,我们已经了解了如何发送一个简单的电子邮件。但是,我们需要发送一个包含文本和附件的更为复杂的电子邮件。这就需要使用MIME消息,该消息提供处理多用途电子邮件的功能。MIME消息需要不同部分的边界以及额外的头信息来指定要发送的内容。MIMEBase类是一个Message的抽象子类并且能够发送多部分类型的邮件。由于这是一个抽象子类,因此你不能创建真正意义的实例。不过你可以使用其中的一个子类,比如MIMEText来实现。mail()函数中的最后一步创建一个新的SMTP对象来指向126邮件服务,传递用户名和密码来连接该邮件服务,发送邮件最后关闭连接。

访问FTP服务器中的文件

对于GIS程序员来说获取FTP服务器中的文件进行处理也是非常普遍的操作,并且这类操作页可以利用Python脚本来实现自动化处理。

Getting ready

通过ftplib模块可以完成连接FTP服务器并下载文件操作。FTP对象接受一个主机名称,一个用户名以及密码参数来创建一个与FTP服务器的连接。连接打开之后,你就可以查找并下载文件了。
在本案例中,你将连接到NASA的某FTP站点下载一副TIF格式的图像

How to do it...

按照以下步骤创建脚本来连接到一个FTP服务器并下载文件:
1.打开IDLE,创建一个脚本并保存为C:\ArcpyBook\Appendix2\ftp.py
2.我们将要连接到NASA的FTP服务器。访问网站ftp://is.sci.gsfc.nasa.gov
3.导入ftplibossocket模块:

import ftplib
import os
import socket

4.添加以下变量分别定义URL地址,目录和文件名:

HOST = "is.sci.gsfc.nasa.gov"
DIRN=  "/testdata/BLUEMARBLE_POSTER_IMAGES/"
FILE = "FLOOD_VNCLR_d20140601_t0612599_e0614240_BEFORE.tif"

5.添加以下语句块创建一个连接。如果连接出现错误会生成一条错误消息。如果连接成功则会显示一条成功连接的消息:

try:
    f = ftplib.FTP(HOST)
except (socket.error,socket.gaierror),e:
    print "ERROR: cannot reach '%s'" % HOST
print "*** Connected to host '%s'" % HOST

6.添加以下语句块来匿名方式登录服务器:

try:
    f.login()
except ftplib.error_perm:
    print "ERROR: cannot login anonymously"
    f.quit()
print "*** Logged in as 'anonymous'"

7.添加以下语句块将当期目录更新至DIRN变量中指定的目录:

try:
    f.cwd(DIRN)
except ftplib.error_perm:
    print "ERROR: cannot CD to '%s'" % DIRN
    f.quit()
print  "*** Changed to '%s'" % DIRN

8.调用FTP.retrbinary()函数获取数据文件:

try:
    f.retrbinary("RETR %s" %FILE,open(FILE,'wb').write)
except ftplib.error_perm:
    print "ERROR: cannot read file '%s'" % FILE
    os.unlink(FILE)
else:
    print  "*** Downloaded  '%s' to CWD" % FILE

9.断开与服务器的连接:

f.quit()

10.完整代码如下:

import ftplib
import os
import socket
HOST = "is.sci.gsfc.nasa.gov"
DIRN=  "/testdata/BLUEMARBLE_POSTER_IMAGES/"
FILE = "FLOOD_VNCLR_d20140601_t0612599_e0614240_BEFORE.tif"
try:
    f = ftplib.FTP(HOST)
    print "*** Connected to host '%s'" % HOST
    try:
        f.login()
        print "*** Logged in as 'anonymous'"
        try:
            f.cwd(DIRN)
            print  "*** Changed to '%s'" % DIRN
            try:
                f.retrbinary("RETR %s" %FILE,open(FILE,'wb').write)
            except ftplib.error_perm:
                print "ERROR: cannot read file '%s'" % FILE
                os.unlink(FILE)
            else:
                print  "*** Downloaded  '%s' to CWD" % FILE
            finally:
                f.quit()
        except ftplib.error_perm:
            print "ERROR: cannot CD to '%s'" % DIRN
            f.quit()        
    except ftplib.error_perm:
        print "ERROR: cannot login anonymously"
        f.quit()   
except (socket.error,socket.gaierror),e:
    print "ERROR: cannot reach '%s'" % HOST

11.保存并运行脚本。如果一切顺利的话,你会看到如下结果显示:

*** Connected to host 'is.sci.gsfc.nasa.gov'
*** Logged in as 'anonymous'
*** Changed to '/testdata/BLUEMARBLE_POSTER_IMAGES/'
*** Downloaded  'FLOOD_VNCLR_d20140601_t0612599_e0614240_BEFORE.tif' to CWD

12.查看C:\ArcpyBook\Appendix2目录下的文件。默认情况下,FTP会将文件下载到当前工作目录中(同python脚本文件位于同一目录下):

How it works...

连接FTP服务器之前,你需要先知道URL地址。你还需要知道要下载文件的文件名和所在目录。在脚本中,我们已经对这些信息进行硬编码处理,这样你就可以专注于应用FTP相关的功能。利用这些信息我们随后会创建一个NASA的FTP服务器的连接。这可以通过ftplib.FTP()函数接受一个URL地址作为主机参数来完成。
is.sci.gsfc.nasa.gov服务器接受匿名登录,因此我们采用这样方式来连接服务器。需要注意一点,如果服务器不接受匿名登录方式,你就需要提供一个用户名和密码。登录成功后,随后会将当前的根目录地址更改为DIRN变量中定义的目录。这一步通过调用cwd(<path>)函数来实现。随后调用retrbinary()函数来下载kmz文件。最后,你还需要在下载完成后断开与FTP服务器的连接。这一步可通过调用quit()方法完成。

There's more...

你还可以调用其他与FTP相关的方法来执行不同的操作。通常来讲,这些方法可分为目录级别操作与文件级别操作。目录级别方法包括dir()方法用来获取目录中的文件列表,mkd()方法用来创建一个新的目录,pwd()方法来获取当前的工作目录,而cwd()方法则更改当前目录位置。
ftplib模块还包括与文件操作相关的方法。你可以上传或下载二进制文件或纯文本文件。retrbinary()storbinary()方法则分别用于获取和保存文件。纯文本文件可以调用retrlines()storlines()方法来获取和保存。
你还可以关注FTP类中的其他方法。调用delete()方法可以删除文件,而rename()方法可以重命名文件。你还可以通过调用sendcmd()方法来向FTP服务器发送指令。

创建ZIP文件

GIS日常业务中需要将大文件压缩为.zip格式便于共享。你可以使用Python提供的模块来解压缩.zip格式文件。

Getting ready

Zip格式是一种常用的压缩归档格式,该格式可以使用Python中的zipfile模块进行处理。ZipFile类可用于创建,读取以及写入.zip文件。创建一个新的.zip文件,你只要提供一个文件名以及模式参数,比如w模式则表明你想要对文件写入数据。下面的代码示例中,我们创建一个叫做dataFile.zip的文件。第二个参数w表示会创建一个新文件。在写入模式中会创建一个新文件或覆盖带相同名称的已有文件。一个可选的压缩参数可在创建文件时使用。该参数可以设置为ZIP_STORED或者ZIP_DEFLATED

zipfile.ZipFile("dataFile.zip","w","ZIP_STORED")

在本案例中,你会将位于C:\ArcpyBook\data目录下的所有shapefile文件打包压缩成一个zip格式的压缩文件。

How to do it...

按照以下步骤来学习如何编写脚本来创建一个.zip文件:
1.打开IDLE,创建一个脚本文件并保存为C:\ArcpyBook\Appendix2\CreateZipfile.py
2.导入zipfileos模块:

import zipfile
import os

3.以写入模式创建一个新的shapefile.zip文件,并添加一个压缩参数:

zfile = zipfile.ZipFile("shapefile.zip","w",zipfile.ZIP_STORED)

4.下一步,我们会调用os.listdir()函数来创建数据目录中的文件列表:

files = os.listdir("C:/ArcpyBook/data")

5.循环遍历了列表中的文件,如果文件扩展名为shpshxdbf则写入.zip文件中:

for f in files:
    if f.endswith("shp") or f.endswith("shx") or f.endswith("dbf"):
        zfile.write("C:/ArcpyBook/data/" + f)

6.打印文件列表中所有写入到zip文件中的文件。你可以调用ZipFile.namelist()函数来创建压缩文件中的文件列表:

for f in zipfile.namelist():
    print "Added %s" % f

7.关闭.zip文件:

zfile.close()

8.完整代码如下;

import zipfile
import os
zfile = zipfile.ZipFile("shapefile.zip","w",zipfile.ZIP_STORED)
files = os.listdir("C:/ArcpyBook/data")
for f in files:
    if f.endwith("shp") or f.endwith("shx") or f.endwith("dbf"):
        zfile.write("C:/ArcpyBook/data/" + f)
for f in zfile.namelist():
    print "Added %s" % f
zfile.close()

9.保存并运行代码。你会看到如下结果显示:

Added ArcpyBook/data/Burglaries_2009.dbf
Added ArcpyBook/data/Burglaries_2009.shp
Added ArcpyBook/data/Burglaries_2009.shx
Added ArcpyBook/data/Streams.dbf
Added ArcpyBook/data/Streams.shp
Added ArcpyBook/data/Streams.shx

10.在资源管理器中,你可以看到如下图所示的.zip文件。注意压缩文件的大小(文件大小视文件夹中满足条件的文件决定),该文件没有进行压缩:

11.现在我们要创建一个压缩版本的.zip文件看一看有什么变化。如下所示修改代码:

zfile = zipfile.ZipFile("shapefile2.zip","w",zipfile.ZIP_DEFLATED)

12.保存后运行脚本。
13.查看你刚才创建的shapefile2.zip文件的大小。压缩后文件变小了:

How it works...

在本案例中,我们以写入模式创建了一个叫做shapefile.zip的文件。在第一版脚本中,我们没有压缩文件内容。第二个版本中我们在ZipFile对象构造函数中使用了DEFLATED参数来实现文件内容的压缩。随后脚本获取数据目录中的文件列表并循环遍历每一个文件。随后通过调用write()函数将扩展名为.shp.shx.dbf的文件写入到压缩文件中。最后,压缩文件中的所有文件名打印输出到屏幕中。

There's more...

保存在ZIP压缩文件中的内容可以通过调用read()方法来进行读取。首先文件以读取模式打开,随后调用read()方法并接受一个表示需要读取的文件名参数。文件内容之后既可以选择打印输出到屏幕上,也可以写入到其他文件中或保存为列表或字典变量中。举个例子,readme.zip压缩文件中包含一个readme.txt文件,下面的脚本代码就可以实现读取readme.txt文件文本内容的功能:

import zipfile
zipFile=zipfile.ZipFile("readme.zip","r")
fcontent=zipFile.read("readme.txt")
print fcontent
zipFile.close()

读取XML文件

XML文件是一种传输数据和保存数据的格式。由于数据是保存在纯文本文件中,因此XML文件是不依赖平台的。结构上类似于HTML,不过HTML用于显示数据而XML则是用于数据传输。XML文件有时候会作为不同软件系统之间的GIS数据交换格式。

Getting ready

XML文档是一个树形结构,由根元素,子元素以及元素属性构成。元素通常称作节点(Node)。所有的XML文件都包含一个根元素。根元素是所有其他元素或子节点的父元素。下面的示例代码则展示了一个XML文档结构。不同于HTML文件,XML文件大小写敏感:

<root>
    <child att="value">
    <subchild>....</subchild>
    </child>
</root>

Python提供了多个用于处理XML文件的模块。具体使用哪个模块应该由所执行的操作来决定。不要试图使用单个模块来解决所有问题。每一个模块都有自己擅长处理的特定功能。在本案例中,你会学习如何使用文档中的nodeselement属性来读取XML文件中的数据。
你可以使用许多方法来访问XML文档中的节点属性。查找节点的标签名称可能是最简单的方式,然后遍历包含子节点列表的目录树。在进行以上操作之前,你需要调用minidom.parse()方法来解析XML文档。解析文档后,你就可以使用childNodes属性获取一个包含了从根元素开始的所有子节点的列表。最后调用getElementsByTagName(tag)函数来根据标签名称查找节点。该函数会返回一个与tag有关的所有子节点列表。
你还可以通过调用hasAttribute(name)方法来查看节点是否包含某个属性名称,该函数返回一个布尔值。确定属性存在后调用getAttribute(name)方法获取该属性值。
在本案例中将解析一个XML文件并提取出与某个特定元素(节点)和属性有关的值。在该文件中,我们会从所有的节点中查找<fire>节点和address属性,查找到的address属性值会打印到屏幕上。

How to do it...

1.打开IDLE,创建一个脚本并保存为
C:\ArcpyBook\Appendix2\XMLAccessElementAttribute.py
2.我们以位于C:\ArcpyBook\Appendix2文件夹中的WitchFireResidenceDestroyed.xml文件为例。下面是该文件的部分内容:

<fires>
<fire address="11389 Pajaro Way" city="San Diego"
state="CA" zip="92127" country="USA" latitude="33.037187" longitude="-117.082299" />
<fire address="18157 Valladares Dr" city="San Diego" state="CA" zip="92127" country="USA" latitude="33.039406" longitude="-117.076344" />
<fire address="11691 Agreste Pl" city="San Diego" state="CA" zip="92127" country="USA" latitude="33.036575" longitude="-117.077702" />
<fire address="18055 Polvera Way" city="San Diego" state="CA" zip="92128" country="USA" latitude="33.044726" longitude="-117.057649" />
</fires>

3.从xml.dom模块中导入minidom

from xml.dom import minidom

4.解析XML文件:

xmldoc = minidom.parse("WitchFireResidenceDestroyed.xml")

5.创建XML文件中的节点列表:

childNodes = xmldoc.childNodes

6.生成一个包含所有<fire>节点的列表:

eList = childNodes[0].getElementsByTagName("fire")

7.循环遍历列表中的元素,检测是否存在address属性。如果存在该属性则打印该属性值:

for e in eList:
    if e.hasAttribute("address"):
        print e.getAttribute("address")

8.保存并运行脚本。你会看到如下结果显示:

11389 Pajaro Way
18157 Valladares Dr
11691 Agreste Pl
18055 Polvera Way
18829 Bernardo Trails Dr
18189 Chretien Ct
17837 Corazon Pl
18187 Valladares Dr
18658 Locksley St
18560 Lancashire Way
........
18682 Lancashire Way
18344 Lincolnshire St
How it works...

在脚本中加载XML文档是处理XML文件最为基础的事情,你可以使用xml.dom模块中minidom对象来完成。minidom对象包含的parse()方法可接受一个xml文档路径并创建xml文件的文档对象模型(DOM)树对象。

DOM树中的childNodes属性生成一个包含XML文件中所有节点的列表。随后可以调用getElementsByTagName()方法来访问这些节点。最后一步就是循环遍历包含在eList变量中的所有<fire>节点。对于每一个节点,调用hasAttribute()方法来检测是否包含address属性,如果存在则调用getAttribute()方法并将属性值打印输出到屏幕中。

There's more...

有时候你可能需要在XML文档中查找一个特定的文本字符串。这就需要使用xml.parsers.expat模块。你需要从expat类中获取一个搜索类,之后创建该类的一个对象。创建完成后,你可以对搜索对象调用parse()方法来查找数据。最后调用getElementsByTagName()方法根据标签名称来查找节点,这就返回一个与标签名称有关的所有子节点列表。


附录A 自动执行Python脚本 |||

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 141,232评论 1 296
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 60,610评论 1 254
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 93,049评论 0 210
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 40,691评论 0 171
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 48,375评论 1 250
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 38,571评论 1 169
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 30,262评论 2 266
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,036评论 0 163
  • 想象着我的养父在大火中拼命挣扎,窒息,最后皮肤化为焦炭。我心中就已经是抑制不住地欢快,这就叫做以其人之道,还治其人...
    爱写小说的胖达阅读 28,781评论 6 225
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 32,394评论 0 211
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,154评论 2 212
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 30,470评论 1 222
  • 白月光回国,霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前, 不然我有一百种方法让你生不如死。]我...
    爱写小说的胖达阅读 24,151评论 0 31
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,023评论 2 210
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 31,376评论 3 201
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,579评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 25,926评论 0 163
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 33,342评论 2 227
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 33,466评论 2 229

推荐阅读更多精彩内容