我在python中编写解析器来解析xml文件。为此,我需要得到标签名称,但是当我这样做时,除了标签名称,我也得到了名称空间。与此同时,我需要在许多位置获得第一个孩子,我无法在此包中找到任何属性(Elementtree)。我搜索了很多,但无法找到如何获得没有名称空间值的标签名称和第一个孩子。 trialinput.xml文件如下:
<?xml version="1.0"?>
<nf:rpc-reply xmlns:nf="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="http://www.cisco.com/nxos:1.0:ip">
<nf:data>
<show>
<ip>
<interface>
<__XML__BLK_Cmd_ip_show_interface_command_brief>
<__XML__OPT_Cmd_ip_show_interface_command_operational>
<__XML__OPT_Cmd_ip_show_interface_command_vrf>
<__XML__OPT_Cmd_ip_show_interface_command___readonly__>
<__readonly__>
<TABLE_intf>
<ROW_intf>
<vrf-name-out>default</vrf-name-out>
<intf-name>Vlan10</intf-name>
<prefix>9.1.1.1</prefix>
<ip-disabled>FALSE</ip-disabled>
<iod>104</iod>
<proto-state>TRUE</proto-state>
<link-state>TRUE</link-state>
<admin-state>TRUE</admin-state>
</ROW_intf>
<ROW_intf>
<vrf-name-out>default</vrf-name-out>
<intf-name>Vlan23</intf-name>
<prefix>23.1.1.9</prefix>
<ip-disabled>FALSE</ip-disabled>
<iod>103</iod>
<proto-state>TRUE</proto-state>
<link-state>TRUE</link-state>
<admin-state>TRUE</admin-state>
</ROW_intf>
<ROW_intf>
<vrf-name-out>default</vrf-name-out>
<intf-name>Po1</intf-name>
<prefix>4.9.1.2</prefix>
<ip-disabled>FALSE</ip-disabled>
<iod>111</iod>
<proto-state>TRUE</proto-state>
<link-state>TRUE</link-state>
<admin-state>TRUE</admin-state>
</ROW_intf>
<ROW_intf>
<vrf-name-out>default</vrf-name-out>
<intf-name>Po2</intf-name>
<prefix>5.9.1.2</prefix>
<ip-disabled>FALSE</ip-disabled>
<iod>112</iod>
<proto-state>TRUE</proto-state>
<link-state>TRUE</link-state>
<admin-state>TRUE</admin-state>
</ROW_intf>
<ROW_intf>
<vrf-name-out>default</vrf-name-out>
<intf-name>Po3</intf-name>
<prefix>6.9.1.2</prefix>
<ip-disabled>FALSE</ip-disabled>
<iod>113</iod>
<proto-state>TRUE</proto-state>
<link-state>TRUE</link-state>
<admin-state>TRUE</admin-state>
</ROW_intf>
</TABLE_intf>
</__readonly__>
</__XML__OPT_Cmd_ip_show_interface_command___readonly__>
</__XML__OPT_Cmd_ip_show_interface_command_vrf>
</__XML__OPT_Cmd_ip_show_interface_command_operational>
</__XML__BLK_Cmd_ip_show_interface_command_brief>
</interface>
</ip>
</show>
</nf:data>
</nf:rpc-reply>
我正在编写的代码(在完成过程中,只是为了给出我想要作为输出的内容的要点):
import xml.etree.ElementTree as ET
print "before skip()"
def skip(root):
print "rootname.tag in skip == %s" %(root.tag)
if(root.tag == "readonly"): // here if I compare with the namespace then returns the value
print "skip -> if"
return root
else:
print "skip-> else"
root = root[0]
print "new root %s" %root
return skip(root)
xmlDoc = ET.parse("trialinput.xml")
dict = {}
print "accessing the root"
root = xmlDoc.getroot()
print "rootname == %s" %root.tag
pointerOfReadonly = skip(root)
print "pointerOfReadonly.tag %s" %pointerOfReadonly.tag
print "accessing child of readonly"
tableInitiationPointer = pointerOfReadonly[0] // Here how to get the first child of readonly tag?
#print "accessing children of table"
#allRows = tableInitiationPointer.childNodes
Print "no of rows in the table = %s" %tableInitiationPointer.len("ROW_intf")// Returning none due to above non ability to find the tag
for row in tableInitiationPointer:
for subrows in row:
key = subrows.tag
value = subrows.value
dict[key]=value
答案 0 :(得分:0)
要删除标记上的命名空间:
import re
def GetBareTag(tag): return re.sub(r'{.*?}', '', tag)
找到第一个孩子:
def GetFirstChild(e): return e[0] if len(e) else None
答案 1 :(得分:0)
您缺少的是正确使用命名空间。
由于您的xml文件中有名称空间,因此节点将具有名称空间,ET将返回名称空间以及tag
。
尝试以下内容来提取正确的节点:
xmlDoc = ET.parse("trialinput.xml")
dict = {}
print "accessing the root"
root = xmlDoc.getroot()
print "rootname == %s" %root.tag
pointerOfReadonly = root.findall(".//{http://www.cisco.com/nxos:1.0:ip}__readonly__")
print pointerOfReadonly
前2个节点rpc-reply
和data
将包含名称空间"urn:ietf:params:xml:ns:netconf:base:1.0"
,其他节点将包含"http://www.cisco.com/nxos:1.0:ip"
有关xpath
语法和用法的概述,请查看docs
因此,当您搜索节点__readonly__
时,您需要在findall()
方法中明确指定名称空间,如:
pointerOfReadonly = root.findall(".//{http://www.cisco.com/nxos:1.0:ip}__readonly__")
print pointerOfReadonly
打印所有找到的节点的列表(在我们的例子中只有1个):
[<Element '{http://www.cisco.com/nxos:1.0:ip}__readonly__' at 0x20b4990>]
然后,您需要按照与要搜索的其他节点类似的技术。
对于例如现在,如果要查找节点ROW_intf
,可以执行以下操作:
pointerOfRowIntf = root.findall(".//{http://www.cisco.com/nxos:1.0:ip}ROW_intf")
print pointerOfRowIntf
然后打印所有5个找到的节点:
[<Element '{http://www.cisco.com/nxos:1.0:ip}ROW_intf' at 0x20d4990>, <Element '{http://www.cisco.com/nxos:1.0:ip}ROW_intf' at 0x20d4bb0>, <Element '{http://www.cisco.com/nxos:1.0:ip}ROW_intf' at 0x20d4db0>, <Element '{http://www.cisco.com/nxos:1.0:ip}ROW_intf' at 0x20d4f90>, <Element '{http://www.cisco.com/nxos:1.0:ip}ROW_intf' at 0x20dc190>]