Python自带xml模块实现xpath查询带xmlns命名空间的xml

需求

手上有个项目需要解析xml数据,参考写爬虫的经验,容易想到使用XPath语句进行节点导航。

XPath 是一门在 XML 文档中查找信息的语言,用于在 XML 文档中通过元素和属性进行导航。
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

查阅

网上搜了一下,大多推荐使用lxml模块而非自带的xml进行查询,三方库确实强大,但lxml需要单独安装,通用性不足,希望尽量用系统自带的xml实现。

文档指出xml.etree.ElementTree可以通过支持的有限的XPath表达式来定位元素,支持语法如下:

语法 说明
tag 查找所有具有指定名称tag的子元素。例如:country表示所有名为country的元素,country/rank表示所有名为country的元素下名为rank的元素。
* 查找所有元素。如:*/rank表示所有名为rank的孙子元素。
. 选择当前元素。在xpath表达式开头使用,表示相对路径。
// 选择当前元素下所有级别的所有子元素。xpath不能以“//”开头。
.. 选择父元素。如果视图达到起始元素的祖先,则返回None(或空列表)。起始元素为调用find(或findall)的元素。
[@attrib] 选择具有指定属性attrib的所有子元素。
[@attrib='value'] 选择指定属性attrib具有指定值value的元素,该值不能包含引号。
[tag] 选择所有具有名为tag的子元素的元素。
[.='text'] Python3.7+,选择元素(或其子元素)完整文本内容为指定的值text的元素。
[tag='text'] 选择元素(或其子元素)名为tag,完整文本内容为指定的值text的元素。
[position] 选择位于给定位置的所有元素,position可以是以1为起始的整数、表达式last()或相对于最后一个位置的位置(如:last()-1)

上述完全能够涵盖我的查询工作,决定实现。

实现

代码如下

import xml.etree.cElementTree as ET

tree = ET.ElementTree(file="./reference.kml")
marks = tree.findall(".//Placemark")

注意这里的XPath不支持直接用//而要写作.//
上述代码没有报错,但返回list始终为[]无法匹配节点

思考

进入debug console查看tree变量显示存在根节点,也可以用tree[0][1][2]进行导航,我???
查看tag名称显示为{http://opengis.net/kml/2.2}XXX比较奇怪

此时xml文件开头的<kml xmlns="http://opengis.net/kml/2.2">引起了我的注意
这不就是tag里多出来的字段?

进一步查阅,xmlns全称为xml namespace类似C++的命名空间,用于解决局部名称重复冲突。
进一步的,存在xmlns则需要在XPath查询时指定namespace字典进行导航。

解决

添加namespaces属性即可

import xml.etree.cElementTree as ET
NS = {"i":"http://opengis.net/kml/2.2"}
tree = ET.ElementTree(file="./reference.kml")
marks = tree.findall(".//i:Placemark",namespaces=NS)

查询正常,能够返回匹配的list结果。

原文链接: https://www.cnblogs.com/azureology/p/13144388.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    Python自带xml模块实现xpath查询带xmlns命名空间的xml

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/355771

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午10:31
下一篇 2023年3月2日 上午10:31

相关推荐