如何用Python基于动态XML过滤器提取目标XML对应内容?
动态XML内容过滤实现
需求说明
现有目标XML文件(包含ISIS配置),以及动态变化的过滤XML模板,需要从目标XML中提取与过滤XML结构匹配的所有子标签及对应值,不能在代码中硬编码任何固定标签。
示例目标XML
<isis xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-clns-isis-cfg"> <instances> <instance> <instance-name>ISIS-TEST</instance-name> <running></running> <overload-bits> <overload-bit> <level>level2</level> <overload-bit-mode>startup-period</overload-bit-mode> <hippity-period>360</hippity-period> </overload-bit> </overload-bits> <is-type>level2</is-type> <nets> <net> <net-name>49.0088.0088.2000.0088.00</net-name> </net> </nets> <afs> <af> <af-name>ipv4</af-name> <saf-name>unicast</saf-name> <af-data> <metri-styles> <metric-style> <level>not-set</level> </metric-style> </metri-styles> </af-data> </af> </afs> <interfaces> <interface> <interface-name>Loopback0</interface-name> <running></running> <state>passive</state> <interface-afs> <interface-af> <af-name>ipv4</af-name> </interface-af> </interface-afs> </interface> <interface> <interface-name>Bundle-Ether88.88</interface-name> <running></running> <state>suppressed</state> <circuit-type>level2</circuit-type> <point-to-pont></point-to-pont> <interface-afs> <interface-af> <af-name>ipv4</af-name> </interface-af> </interface-afs> </interface> </interfaces> </instance> </instances> </isis>
示例过滤XML
<isis xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-clns-isis-cfg"> <interfaces> </interfaces> </isis>
实现方案(基于Python lxml库)
利用lxml的XML解析能力,通过递归遍历过滤XML的节点结构,在目标XML中定位对应路径的节点并复制内容,实现完全动态的过滤逻辑。
代码实现
from lxml import etree def filter_xml(target_tree, filter_tree): # 获取XML默认命名空间,适配带xmlns的节点查询 ns = target_tree.getroot().nsmap.get(None, "") ns_map = {"ns": ns} if ns else {} def recursive_match(target_parent, filter_parent, result_parent): # 遍历过滤模板的子节点 for filter_child in filter_parent: filter_tag = etree.QName(filter_child).localname # 在目标XML的当前父节点下查找所有匹配标签的子节点 target_children = target_parent.xpath(f"./ns:{filter_tag}", namespaces=ns_map) for target_child in target_children: # 复制目标节点到结果树中 result_child = etree.SubElement(result_parent, filter_child.tag) result_child.text = target_child.text result_child.attrib.update(target_child.attrib) # 如果过滤节点还有子节点,继续递归匹配深层结构 if len(filter_child) > 0: recursive_match(target_child, filter_child, result_child) # 初始化结果根节点,继承目标XML的命名空间映射 result_root = etree.Element(filter_tree.getroot().tag, nsmap=target_tree.getroot().nsmap) # 启动递归匹配流程 recursive_match(target_tree.getroot(), filter_tree.getroot(), result_root) return etree.ElementTree(result_root) # 加载目标XML和过滤XML(可替换为文件路径加载:etree.parse("target.xml")) target_tree = etree.fromstring("""<isis xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-clns-isis-cfg">...</isis>""") filter_tree = etree.fromstring("""<isis xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-clns-isis-cfg"><interfaces></interfaces></isis>""") # 执行过滤并输出结果 result_tree = filter_xml(target_tree, filter_tree) print(etree.tostring(result_tree, pretty_print=True, encoding="utf-8").decode())
关键逻辑说明
- 命名空间兼容:自动识别XML的默认命名空间,确保XPath查询能正确匹配带命名空间的节点。
- 递归动态匹配:完全基于过滤XML的结构递归查找目标节点,无需硬编码任何标签名称,适配任意结构的过滤模板。
- 完整节点复制:复制匹配节点的文本、属性及所有子节点,保留原XML的结构完整性。
示例输出结果
<isis xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-clns-isis-cfg"> <interfaces> <interface> <interface-name>Loopback0</interface-name> <running></running> <state>passive</state> <interface-afs> <interface-af> <af-name>ipv4</af-name> </interface-af> </interface-afs> </interface> <interface> <interface-name>Bundle-Ether88.88</interface-name> <running></running> <state>suppressed</state> <circuit-type>level2</circuit-type> <point-to-pont></point-to-pont> <interface-afs> <interface-af> <af-name>ipv4</af-name> </interface-af> </interface-afs> </interface> </interfaces> </isis>
内容的提问来源于stack exchange,提问作者kootlas
相关产品推荐
相关产品推荐

