python使用lxml解析命名空间xml

python使用lxml解析命名空间xml

python解析xml使用较简单的是用lxml包来解析,最方便获取节点的是通过xpath语法,但是带命名空间的xml文档就无法正常解析到,需要在解析时加入namespace的命名空间头信息,折腾半天,特记录如下:

示例xml


	
		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

你可能感兴趣的:(python)