You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ElementTree解析特定XML仅获根元素,报KeyError: 'size'问题求助

问题:解析海康威视摄像头OSD XML配置时触发KeyError

问题场景

编写Python脚本获取摄像头OSD配置并提取Inventory ID,已实现XML下载与解析逻辑,但解析第二个配置文件时抛出KeyError: 'size'异常。

原代码

import xml.etree.ElementTree as ET

first_config = """
<VideoOverlay xmlns="http://www.hikvision.com/ver20/XMLSchema" version="2.0">
<normalizedScreenSize>
<normalizedScreenWidth>704</normalizedScreenWidth>
<normalizedScreenHeight>576</normalizedScreenHeight>
</normalizedScreenSize>
<attribute>
<transparent>false</transparent>
<flashing>false</flashing>
</attribute>
<TextOverlayList size="4">
<TextOverlay>
<id>1</id>
<enabled>true</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<displayText>Inv: 1234513454321</displayText>
<directAngle/>
</TextOverlay>
</TextOverlayList>
<DateTimeOverlay>
<enabled>true</enabled>
<positionX>552</positionX>
<positionY>560</positionY>
<dateStyle>DD-MM-YYYY</dateStyle>
<timeStyle>24hour</timeStyle>
<displayWeek>false</displayWeek>
</DateTimeOverlay>
<channelNameOverlay>
<enabled>true</enabled>
<positionX>553</positionX>
<positionY>48</positionY>
</channelNameOverlay>
<fontSize>48*48</fontSize>
<frontColorMode>auto</frontColorMode>
<frontColor>000000</frontColor>
<alignment>customize</alignment>
<boundary>1</boundary>
</VideoOverlay>
"""

second_config = """
<VideoOverlay xmlns="http://www.hikvision.com/ver20/XMLSchema" version="2.0">
<normalizedScreenSize>
<normalizedScreenWidth>704</normalizedScreenWidth>
<normalizedScreenHeight>576</normalizedScreenHeight>
</normalizedScreenSize>
<attribute>
<transparent>false</transparent>
<flashing>false</flashing>
</attribute>
<fontSize>48*48</fontSize>
<TextOverlayList size="8">
<TextOverlay>
<id>1</id>
<enabled>true</enabled>
<positionX>3</positionX>
<positionY>48</positionY>
<displayText>Inv: 100000000</displayText>
<isPersistentText>true</isPersistentText>
</TextOverlay>
<TextOverlay>
<id>2</id>
<enabled>true</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<displayText>GEO:0000000000</displayText>
<isPersistentText>true</isPersistentText>
</TextOverlay>
<TextOverlay>
<id>3</id>
<enabled>true</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<displayText>Serial:000000000</displayText>
<isPersistentText>true</isPersistentText>
</TextOverlay>
<TextOverlay>
<id>4</id>
<enabled>true</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<displayText>MODEL:0000000000000</displayText>
<isPersistentText>true</isPersistentText>
</TextOverlay>
<TextOverlay>
<id>5</id>
<enabled>false</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<displayText/>
<isPersistentText>true</isPersistentText>
</TextOverlay>
<TextOverlay>
<id>6</id>
<enabled>false</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<displayText/>
<isPersistentText>true</isPersistentText>
</TextOverlay>
<TextOverlay>
<id>7</id>
<enabled>false</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<displayText/>
<isPersistentText>true</isPersistentText>
</TextOverlay>
<TextOverlay>
<id>8</id>
<enabled>false</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<displayText/>
<isPersistentText>true</isPersistentText>
</TextOverlay>
</TextOverlayList>
<DateTimeOverlay>
<enabled>true</enabled>
<positionX>0</positionX>
<positionY>576</positionY>
<dateStyle>DD-MM-YYYY</dateStyle>
<timeStyle>24hour</timeStyle>
<displayWeek>false</displayWeek>
</DateTimeOverlay>
<channelNameOverlay xmlns="http://www.hikvision.com/ver20/XMLSchema" version="2.0">
<enabled>true</enabled>
<positionX>581</positionX>
<positionY>48</positionY>
</channelNameOverlay>
<frontColorMode>auto</frontColorMode>
<frontColor>000000</frontColor>
<alignment>customize</alignment>
<boundary>1</boundary>
<upDownboundary>0</upDownboundary>
<leftRightboundary>0</leftRightboundary>
</VideoOverlay>
"""

xml_string = first_config

root = ET.fromstring(xml_string)
print(root.tag)

osd_list_size = root[2].attrib['size']
print(osd_list_size) #size of the list of OSD lines

for child in root[2]:
    print(child[4].text)

xml_string = second_config

root_b = ET.fromstring(xml_string)
print(root_b.tag)

osd_list_size = root_b[2].attrib['size']
print(osd_list_size) #size of the list of OSD lines

for child in root_b[2]:
    print(child[4].text)

报错信息

Traceback (most recent call last):
  File "C:\Users\S26-tech-Dmt\PycharmProjects\pythonProject1\Test.py", line 159, in <module>
    osd_list_size = root_b[2].attrib['size']
                    ~~~~~~~~~~~~~~~~^^^^^^^^
KeyError: 'size'

问题原因

  1. 元素顺序不一致:第一个配置中TextOverlayList是根元素的第3个子元素(索引2),但第二个配置里,根元素的第3个子元素是<fontSize>,TextOverlayList在其后方。直接通过索引访问子元素的方式依赖固定顺序,兼容性极差。
  2. 忽略XML命名空间:XML根元素带有命名空间xmlns="http://www.hikvision.com/ver20/XMLSchema",默认情况下ElementTree查找元素时需要指定命名空间,否则可能无法正确匹配标签。

修复方案

放弃索引定位,改用命名空间+标签名的方式查找目标元素,确保无论元素顺序如何都能正确定位。同时优化Inventory ID的提取逻辑,直接过滤包含Inv:的文本。

修改后的代码

import xml.etree.ElementTree as ET

# 定义XML命名空间
NS = {'hik': 'http://www.hikvision.com/ver20/XMLSchema'}

def extract_inventory_id(xml_content):
    root = ET.fromstring(xml_content)
    # 通过命名空间查找TextOverlayList
    text_overlay_list = root.find('hik:TextOverlayList', NS)
    if not text_overlay_list:
        print("未找到TextOverlayList元素")
        return
    
    # 获取size属性(可选,可根据需求保留)
    osd_list_size = text_overlay_list.attrib.get('size', '未知')
    print(f"OSD列表大小: {osd_list_size}")
    
    # 遍历所有TextOverlay元素
    for overlay in text_overlay_list.findall('hik:TextOverlay', NS):
        display_text = overlay.find('hik:displayText', NS).text
        if display_text and 'Inv:' in display_text:
            # 提取Inventory ID
            inv_id = display_text.split('Inv:')[-1].strip()
            print(f"Inventory ID: {inv_id}")

# 测试第一个配置
print("=== 解析第一个配置 ===")
extract_inventory_id(first_config)

# 测试第二个配置
print("\n=== 解析第二个配置 ===")
extract_inventory_id(second_config)

代码说明

  • 定义命名空间字典NS,用于正确匹配带命名空间的XML标签。
  • 使用find()和findall()方法结合命名空间查找元素,不依赖元素顺序。
  • 通过attrib.get()获取属性,避免KeyError(若属性不存在则返回默认值)。
  • 直接过滤包含Inv:的文本,精准提取Inventory ID,无需依赖固定索引访问子元素。

内容的提问来源于stack exchange,提问作者Tano Dz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:29:50