缺少ELementTree第一个子功能

时间:2014-09-04 12:01:03

标签: python xml parsing

我在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

2 个答案:

答案 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-replydata将包含名称空间"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>]