这是我的解决方案。
所以,最重要的就是读书this https://msdn.microsoft.com/en-us/library/aa468565.aspx正如托马拉克发布的。这是对命名空间的很好的描述并且很容易理解。
我们将使用XPath https://www.w3schools.com/xml/xpath_intro.asp导航 XML 文档。它的表示法类似于文件系统,其中父级和子级由斜杠分隔/。语法已解释here http://www.w3schools.com/xsl/xpath_syntax.asp,但请注意,某些命令对于lxml实现 http://lxml.de/api/lxml.etree.XPath-class.html.
###问题
我们的目标是提取城市名称:内容<name>
这是在<Placemark>
。这是相关的 XML:
<Placemark> <name>CITY NAME</name>
与我上面发布的非功能代码等效的 XPath 是:
tree=etree.parse('kml document')
result=tree.xpath('//Placemark/name/text()')
哪里的text()
需要部分来获取该位置中包含的文本//Placemark/name
.
现在,正如托马拉克指出的那样,这不起作用,因为这两个节点的名称实际上是{http://www.opengis.net/kml/2.2}Placemark
and {http://www.opengis.net/kml/2.2}name
。大括号中的部分是默认命名空间。它没有出现在实际文档中(这让我很困惑),但它是在 XML 文档的开头定义的,如下所示:
xmlns="http://www.opengis.net/kml/2.2"
###解决方案
我们可以通过设置为 xpath 提供命名空间namespaces
争论:
xpath(X, namespaces={prefix: namespace})
对于具有实际前缀的命名空间来说,这很容易,例如在本文档中<gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
哪里的gx
前缀在文档中定义为xmlns:gx="http://www.google.com/kml/ext/2.2"
.
然而,Xpath 不理解默认命名空间是什么(参见docs http://lxml.de/xpathxslt.html)。因此,我们需要欺骗它,就像上面托马拉克建议的那样:我们为默认值发明一个前缀并将其添加到我们的搜索词中。例如,我们可以将其称为 kml。这段代码实际上起到了作用:
tree.xpath('//kml:Placemark/kml:name/text()', namespaces={"kml":"http://www.opengis.net/kml/2.2"})
The tutorial http://lxml.de/xpathxslt.html提到还有一个ETXPath http://lxml.de/api/lxml.etree.ETXPath-class.html方法,其工作方式与 Xpath 类似,只不过将名称空间写在大括号中而不是在字典中定义它们。因此,输入的样式为{http://www.opengis.net/kml/2.2}Placemark
.