python解析xml使用较简单的是用lxml包来解析,最方便获取节点的是通过xpath语法,但是带命名空间的xml文档就无法正常解析到,需要在解析时加入namespace的命名空间头信息,折腾半天,特记录如下:
sp
20181127000077
03880097
031800GS62170804
测试项目
8E14D561A70FA036E0430A97D0E6A036
0318
名称1
0319
名称2
root_node = etree.fromstring(text=xml)
for i in root_node:
print(i.nsmap)
for x in i:
print(x.nsmap)
执行结果
{'test': 'http://schemas.xmltest.org/test/envelope/', 'test-ENV': 'http://schemas.xmltest.org/test/envelope/'}
{'test': 'http://schemas.xmltest.org/test/envelope/', 'test-ENV': 'http://schemas.xmltest.org/test/envelope/', 'xxx': 'http://test.cn'}
{'test': 'http://schemas.xmltest.org/test/envelope/'}
{'test': 'http://schemas.xmltest.org/test/envelope/', None: 'http://test.cn'}
整合到一起
ns = {'xxx': 'http://test.cn', 'test': 'http://schemas.xmltest.org/test/envelope/', 'test-ENV': 'http://schemas.xmltest.org/test/envelope/', None: 'http://test.cn'}
print(root_node.find('.//id',namespaces=ns)) # 获取单节点
print(root_node.findall('.//id',namespaces=ns)) # 获取所有同名节点
也可以直接通过拼接命名空间来获取
print(root_node.findall('.//{http://test.cn}id'))
子节点也同样可以查找到
print(root_node.findall('.//equipmentName', namespaces=ns))
print(root_node.findall('.//{http://test.cn}equipmentName'))
执行结果
[, ]
可以通过循环获取具体内容
for node in root_node.findall('.//equipmentName', namespaces=ns):
print(node.tag.replace('{' + ns['xxx'] + '}', ''), node.text)
结果:
equipmentName 名称1
equipmentName 名称2
循环遍历equipmentObjectList所有子节点
for node in root_node.findall('*//syncAssetListOfCompletedProjRequest//equipmentObjectList', namespaces=ns):
for a in node:
for b in a:
print(b.tag.replace('{' + ns['xxx'] + '}', ''), b.text)
结果:
equipmentCode 0318
equipmentName 名称1
materialObjectList None
equipmentCode 0319
equipmentName 名称2
materialObjectList None