使用lxml解析Python中的XML文件

2 投票
1 回答
4635 浏览
提问于 2025-04-18 11:49

我需要解析一个叫做 example.xml 的 XML 文件,它的内容大概是这样的:

<?xml version="1.0" encoding="ISO-8859-1"?>
<nf:rpc-reply xmlns:nf="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="http://www.cisco.com/nxos:1.0:if_manager">
 <nf:data>
  <show>
   <interface>
    <__XML__OPT_Cmd_show_interface___readonly__>
     <__readonly__>
      <TABLE_interface>
       <ROW_interface>
        <interface>Ethernet1/1</interface>
        <state>down</state>
        <state_rsn_desc>Link not connected</state_rsn_desc>
        <admin_state>up</admin_state>

我想提取出 "interface" 和 "state" 这两个元素,结果应该是这样的:['Ethernet1/1', 'down']。下面是我尝试的解决方案,但它并没有成功:

from lxml import etree

parser = etree.XMLParser()
tree = etree.parse('example.xml', parser)

print tree.xpath('//*/*/*/*/*/*/*/*/interface/text()')
print tree.xpath('//*/*/*/*/*/*/*/*/state/text()')

1 个回答

4

在这里你需要处理命名空间的问题:

from lxml import etree

parser = etree.XMLParser()
tree = etree.parse('example.xml', parser)
ns = {'ns': 'http://www.cisco.com/nxos:1.0:if_manager'}

interface = tree.find('//ns:ROW_interface', namespaces=ns)
print [interface.find('.//ns:interface', namespaces=ns).text,
       interface.find('.//ns:state', namespaces=ns).text]

输出结果是:

['Ethernet1/1', 'down']

使用 collections.namedtuple()

interface_node = tree.find('//ns:ROW_interface', ns)

Interface = namedtuple('Interface', ['interface', 'state'])
interface = Interface(interface=interface_node.find('.//ns:interface', ns).text,
                      state=interface_node.find('.//ns:state', ns).text)

print interface

输出结果是:

Interface(interface='Ethernet1/1', state='down')

撰写回答