2013-07-23 39 views
1

我有一个与Google地球导出的KML有关的问题,因为它似乎不适合元素树。我不知道问题可能在哪里,所以我会解释我是如何做的。元素树不会加载Google地球导出的KML

下面是相关的代码:

kmlFile = open(filePath, 'r').read(-1) # read the whole file as text 
    kmlFile = kmlFile.replace('gx:', 'gx') # we need this as otherwise the Element Tree parser 
               # will give an error 

    kmlData = ET.fromstring(kmlFile) 
    document = kmlData.find('Document') 

有了这个代码,ET(元素树对象)创建 Element对象经由可变kmlData访问。它指向根元素('kml'标记)。但是,当我运行子元素'Document'的搜索时,它将返回None。虽然'文档'标签存在于KML文件中!

除'gx:smth'标签之外,KML和XML之间是否还有其他差异?我已经搜索了我正在处理的KML文件,并没有发现任何可疑内容。下面是一个KML的简化结构文件的程序应该处理:

<?xml version="1.0" encoding="UTF-8"?> 
<kml xmlns="http://earth.google.com/kml/2.2"> 
<Document> 
    <name>UK.kmz</name> 
    <Style id="sh_blu-blank"> 
    <IconStyle> 
     <scale>1.3</scale> 
     <Icon> 
      <href>http://maps.google.com/mapfiles/kml/paddle/blu-blank.png</href> 
     </Icon> 
     <hotSpot x="32" y="1" xunits="pixels" yunits="pixels"/> 
    </IconStyle> 
    <ListStyle> 
     <ItemIcon> 
      <href>http://maps.google.com/mapfiles/kml/paddle/blu-blank-lv.png</href> 
     </ItemIcon> 
    </ListStyle> 
    </Style> 
    [other style tags...] 
    <Folder> 
    <name>UK</name> 
    <Placemark> 
     <name>1262 Crossness Pumping Station</name> 
     <LookAt> 
      <longitude>0.1329926667038817</longitude> 
      <latitude>51.50303535104574</latitude> 
      <altitude>0</altitude> 
      <range>4246.539753518848</range> 
      <tilt>0</tilt> 
      <heading>-4.295161152207489</heading> 
      <altitudeMode>relativeToGround</altitudeMode> 
      <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode> 
     </LookAt> 
     <styleUrl>#msn_blu-blank15000</styleUrl> 
     <Point> 
      <coordinates>0.1389579668507301,51.50888923518947,0</coordinates> 
     </Point> 
    </Placemark> 
     [other placemark tags...] 
    </Folder> 
</Document> 
</kml> 

你有一个想法,为什么我不能访问“KML”的任何子元素?顺便说一下,Python版本是2.7。

回答

1

中的KML文件是在http://earth.google.com/kml/2.2命名空间,通过

<kml xmlns="http://earth.google.com/kml/2.2"> 

所示。这意味着,Document元素的名称是实际上{http://earth.google.com/kml/2.2}Document

取而代之的是:

document = kmlData.find('Document') 

你需要这个:

document = kmlData.find('{http://earth.google.com/kml/2.2}Document') 

然而,与XML文件有问题。有一个名为gx:altitudeMode的元素。 gx位是一个名称空间前缀。这样的前缀需要声明,但声明丢失。

您已经解决了该问题,只需将gx:替换为gx即可。但正确的做法是添加名称空间声明。基于https://developers.google.com/kml/documentation/altitudemode,我认为gxhttp://www.google.com/kml/ext/2.2命名空间相关联。因此,对于得到很好的形成文档,根元素开始标签应该读

<kml xmlns="http://earth.google.com/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2"> 

现在可以将文档解析:

In [1]: from xml.etree import ElementTree as ET 

In [2]: kmlData = ET.parse("kml2.xml") 

In [3]: document = kmlData.find('{http://earth.google.com/kml/2.2}Document') 

In [4]: document 
Out[4]: <Element '{http://earth.google.com/kml/2.2}Document' at 0x1895810> 

In [5]: 
+0

的问题是愚蠢的,因为我不熟悉XML非常许多。我已经探索了一点命名空间,并且类似于您所说的工作......但是,后来我决定在处理它们之前简单地删除与XML中的命名空间无关的任何内容,因为我需要提取的数据是非常简单,没有任何怪异的命名空间。解决这个问题的“正确”方式不值得在我的情况下努力,我会说...但是,谢谢! – user2587828

+0

不客气。如果您希望更多地探索XML名称空间,这可能很有用:http://effbot.org/zone/element-namespaces.htm。官方的ElementTree文档(http://docs.python.org/2/library/xml.etree.elementtree.html)没有多说这个话题。 – mzjn