无法提取XML中所有<sequence-number>标签文本的问题求助
提取XML中标签文本的解决方案
你的代码找不到标签的核心原因是XML命名空间不匹配:<sequence-number>属于http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg这个命名空间,直接用标签名查找会因为lxml默认不识别未声明的命名空间而返回空结果。
以下是两种可行的解决方法:
方法一:使用命名空间映射(推荐)
通过定义命名空间前缀,在XPath中明确指定标签所属的命名空间:
#!/usr/bin/env python from lxml import etree response = ''' <rpc-reply xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:0d07cdf5-c8e5-45d9-89d1-92467ffd7fe4"> <data> <ipv4-acl-and-prefix-list xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg"> <accesses> <access> <access-list-name>TESTTEST</access-list-name> <access-list-entries> <access-list-entry> <sequence-number>1</sequence-number> <remark>TEST</remark> <sequence-str>1</sequence-str> </access-list-entry> <access-list-entry> <sequence-number>10</sequence-number> <grant>permit</grant> <source-network> <source-address>10.10.5.0</source-address> <source-wild-card-bits>0.0.0.255</source-wild-card-bits> </source-network> <next-hop> <next-hop-type>regular-next-hop</next-hop-type> <next-hop-1> <next-hop>10.10.5.2</next-hop> <vrf-name>SANE</vrf-name> </next-hop-1> </next-hop> <sequence-str>10</sequence-str> </access-list-entry> <access-list-entry> <sequence-number>20</sequence-number> <grant>permit</grant> <source-network> <source-address>10.10.6.0</source-address> <source-wild-card-bits>0.0.0.255</source-wild-card-bits> </source-network> <next-hop> <next-hop-type>regular-next-hop</next-hop-type> <next-hop-1> <next-hop>10.10.6.2</next-hop> <vrf-name>VRFNAME</vrf-name> </next-hop-1> </next-hop> <sequence-str>20</sequence-str> </access-list-entry> </access-list-entries> </access> </accesses> </ipv4-acl-and-prefix-list> </data> </rpc-reply> ''' q = etree.fromstring(response) # 定义命名空间映射,前缀可自定义 ns_map = {'cisco': 'http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg'} # 用带命名空间的XPath查找所有sequence-number标签 seq_nodes = q.findall('.//cisco:sequence-number', namespaces=ns_map) # 提取每个标签的文本并转为列表 seq_numbers = [node.text for node in seq_nodes] print(seq_numbers) # 输出: ['1', '10', '20']
方法二:忽略命名空间(临时应急)
如果不需要区分命名空间,可通过local-name()匹配标签名,但这种方法可能误匹配其他命名空间下的同名标签,仅适合简单场景:
seq_nodes = q.findall('.//*[local-name()="sequence-number"]') seq_numbers = [node.text for node in seq_nodes] print(seq_numbers)
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

