使用Element Tree解析XML文件
我有很多个 .xml 文件(大约70个),我需要从中提取一些坐标。显然,最好的方法是使用元素树(element tree)来解析这些xml文件。我刚开始学Python(真的非常非常新手!),对元素树的文档理解起来有点困难!我想知道有没有人能分享一些使用元素树的代码,或者能不能给我解释一下该怎么做……谢谢!
这是我的XML文件中的一个示例……
<?xml version="1.0" encoding="UTF-8" ?>
- <lev:Leveringsinformatie xmlns:lev="http://www.kadaster.nl/schemas/klic/20080722/leveringsinfo">
<lev:Version>1.5</lev:Version>
<lev:Klicnummer>10G179900</lev:Klicnummer>
<lev:Ordernummer>0065491624</lev:Ordernummer>
<lev:RelatienummerGrondroerder>0000305605</lev:RelatienummerGrondroerder>
<lev:Leveringsvolgnummer>1</lev:Leveringsvolgnummer>
<lev:Meldingsoort>Graafmelding</lev:Meldingsoort>
<lev:DatumTijdAanvraag>2010-08-10T11:43:02.779+02:00</lev:DatumTijdAanvraag>
<lev:KlantReferentie>1207-0132-030 - 6</lev:KlantReferentie>
- <lev:Locatie axisLabels="x y" srsDimension="2" srsName="epsg:28992" uomLabels="m m">
- <gml:exterior xmlns:gml="http://www.opengis.net/gml">
- <gml:LinearRing>
<gml:posList>137800.0 484217.0 137796.0 484222.0 137832.0 483757.0 138178.0 483752.0 138174.0 484222.0 137800.0 484217.0</gml:posList>
</gml:LinearRing>
</gml:exterior>
</lev:Locatie>
- <lev:Pngformaat>
- <lev:OmsluitendeRechthoek xmlns:ns4="http://www.kadaster.nl/schemas/klic/20080722/madt" xmlns:bis="http://www.kadaster.nl/schemas/klic/20080722/klicnetbeheerdersinformatieservicetypes" xmlns:ns0="http://www.kadaster.nl/schemas/klic/20080722/gias" xmlns:ns7="http://www.kadaster.nl/schemas/klic/20080722/klicnetbeheerdersinformatieservicetypes" xmlns:madt="http://www.kadaster.nl/schemas/klic/20080722/madt" xmlns:gia="http://www.kadaster.nl/schemas/klic/20080722/gias" xmlns:klic="http://www.kadaster.nl/schemas/20080722/klic" xmlns:b="http://www.kadaster.nl/schemas/klic/20080722/bundelingtypes" xmlns:ns9="http://www.kadaster.nl/schemas/klic/20081010/bmkltypes" xmlns:gml="http://www.opengis.net/gml" xmlns:ns1="http://www.kadaster.nl/schemas/20080722/klic" xmlns:a="http://www.kadaster.nl/schemas/klic/20080722/bundelingservicetypes" xmlns:bmkl="http://www.kadaster.nl/schemas/klic/20081010/bmkltypes" xmlns:ns3="http://www.opengis.net/gml" xmlns:ns8="http://www.kadaster.nl/schemas/klic/20080722/knts">
- <gml:Envelope srsDimension="2" srsName="epsg:28992">
<gml:lowerCorner>137796 483752</gml:lowerCorner>
<gml:upperCorner>138178 484222</gml:upperCorner>
</gml:Envelope>
</lev:OmsluitendeRechthoek>
<lev:PixelsBreed>5348</lev:PixelsBreed>
<lev:PixelsHoog>6580</lev:PixelsHoog>
</lev:Pngformaat>
- <lev:NetbeheerderLeveringen>
- <lev:NetbeheerderLevering>
<lev:RelatienummerNetbeheerder>0000578695</lev:RelatienummerNetbeheerder>
<lev:Bedrijfsnaam>Gemeente Almere</lev:Bedrijfsnaam>
<lev:BedrijfsnaamAfkorting>Gemeente Almere</lev:BedrijfsnaamAfkorting>
我需要提取下角和上角的坐标(lowerCorner/upperCorner)
更新:这是我的完整脚本:
from xml.etree import ElementTree as ET
import sys, string, os, arcgisscripting
gp = arcgisscripting.create(9.3)
workspace = "D:/J040083"
gp.workspace = workspace
for root, dirs, filenames in os.walk(workspace): # returms root, dirs, and files
for filename in filenames:
filename_split = os.path.splitext(filename) # filename and extensionname (extension in [1])
filename_zero = filename_split[0]
extension = str.upper(filename_split[1])
try:
first_2_letters = str.upper(filename_zero[0] + filename_zero[1])
except:
first_2_letters = "XX"
if first_2_letters == "LI" and extension == ".XML":
tree = ET.parse(workspace)
print tree.find('//{http://www.opengis.net/gml}lowerCorner').text
print tree.find('//{http://www.opengis.net/gml}upperCorner').text
现在我遇到了一个错误:
消息 文件名 行 位置
追踪信息
D:\J040083\TXT_EXTRACTION.py 32
parse C:\Python25\Lib\xml\etree\ElementTree.py 862
parse C:\Python25\Lib\xml\etree\ElementTree.py 579
IOError: [Errno 13] 权限被拒绝: 'D:/J040083'
现在我真的很困惑,因为我用一个几乎完全相同的脚本可以访问这些文件!!
2 个回答
使用ElementTree非常简单,基本上就是从一个文件创建一个对象,然后通过名字或路径找到元素,最后获取它们的文本或属性。
在你的情况下稍微复杂一点,因为你的文件里有命名空间,所以我们需要把路径从 ns:tag
的形式转换成 {uri}tag
的形式。这就是 transform_path
函数的目的。
NS_MAP = {
'http://www.kadaster.nl/schemas/klic/20080722/leveringsinfo' : 'lev',
'http://www.opengis.net/gml' : 'gml',
}
INV_NS_MAP = {v:k for k, v in NS_MAP.items()} #inverse ns_map
#for python2: INV_NS_MAP = dict((v,k) for k, v in NS_MAP.iteritems())
#ElementTree expect tags in form {uri}tag, but it would be a pain to have complete uri for eache tag
def transform_path (path):
res = ''
tags = path.split('/')
for tag in tags:
ns, tag = tag.split(':')
res += "{"+INV_NS_MAP[ns]+"}"+tag+'/'
return res
import xml.etree.ElementTree as ET
tree = ET.parse('test.xml')
doc = tree.getroot()
lowerCorner = doc.find(transform_path("lev:Pngformaat/lev:OmsluitendeRechthoek/gml:Envelope/gml:lowerCorner"))
upperCorner = doc.find(transform_path("lev:Pngformaat/lev:OmsluitendeRechthoek/gml:Envelope/gml:upperCorner"))
print (lowerCorner.text) # Print coordinates
print (upperCorner.text) # Print coordinates
#for python2: print elem.text
运行这个脚本和你的文件会得到以下输出:
137796 483752
138178 484222
在处理带有命名空间的ElementTree时,可能会有点棘手。你要找的元素叫做 <gml:lowerCorner>
和 <gml:upperCorner>
。在XML数据的更高层次中,gml
被定义为一个XML命名空间:xmlns:gml="http://www.opengis.net/gml"
。要找到XML树的子元素,可以按照以下方式进行:
from xml.etree import ElementTree as ET
tree = ET.parse('file.xml')
print tree.find('//{http://www.opengis.net/gml}lowerCorner').text
print tree.find('//{http://www.opengis.net/gml}upperCorner').text
输出结果
137796 483752
138178 484222
解释
使用ElementTree的XPath支持,//
可以选择树中所有层级的所有子元素。ElementTree使用{url}tag
的格式来表示特定命名空间中的标签。gml
的URL是http://www.opengis.net/gml
。.text
用来获取元素中的数据。
需要注意的是,//
是查找嵌套节点的快捷方式。在ElementTree的语法中,upperCorner
的完整路径实际上是:
{http://www.kadaster.nl/schemas/klic/20080722/leveringsinfo}Pngformaat/{http://www.kadaster.nl/schemas/klic/20080722/leveringsinfo}OmsluitendeRechthoek/{http://www.opengis.net/gml}Envelope/{http://www.opengis.net/gml}upperCorner