""" Label Studio Configuration Validation Utilities """ from typing import Dict, List, Tuple, Optional import xml.etree.ElementTree as ET class LabelStudioConfigValidator: """验证Label Studio配置的工具类""" # 支持的控件类型 CONTROL_TYPES = { 'Choices', 'RectangleLabels', 'PolygonLabels', 'Labels', 'TextArea', 'Rating', 'KeyPointLabels', 'BrushLabels', 'EllipseLabels', 'VideoRectangle', 'AudioPlus' } # 支持的对象类型 OBJECT_TYPES = { 'Image', 'Text', 'Audio', 'Video', 'HyperText', 'AudioPlus', 'Paragraphs', 'Table' } # 需要子标签的控件类型 LABEL_BASED_CONTROLS = { 'Choices', 'RectangleLabels', 'PolygonLabels', 'Labels', 'KeyPointLabels', 'BrushLabels', 'EllipseLabels' } @staticmethod def validate_xml(xml_string: str) -> Tuple[bool, Optional[str]]: """ 验证XML格式是否正确 Args: xml_string: Label Studio XML配置字符串 Returns: (是否有效, 错误信息) """ try: root = ET.fromstring(xml_string) # 检查根元素 if root.tag != 'View': return False, "Root element must be " # 检查是否有对象定义 objects = [child for child in root if child.tag in LabelStudioConfigValidator.OBJECT_TYPES] if not objects: return False, "No data objects (Image, Text, etc.) found" # 检查是否有控件定义 controls = [child for child in root if child.tag in LabelStudioConfigValidator.CONTROL_TYPES] if not controls: return False, "No annotation controls found" # 验证每个控件 for control in controls: valid, error = LabelStudioConfigValidator._validate_control(control) if not valid: return False, f"Control {control.tag}: {error}" return True, None except ET.ParseError as e: return False, f"XML parse error: {str(e)}" except Exception as e: return False, f"Validation error: {str(e)}" @staticmethod def _validate_control(control: ET.Element) -> Tuple[bool, Optional[str]]: """ 验证单个控件元素 Args: control: 控件XML元素 Returns: (是否有效, 错误信息) """ # 检查必需属性 if 'name' not in control.attrib: return False, "Missing 'name' attribute" if 'toName' not in control.attrib: return False, "Missing 'toName' attribute" # 检查标签型控件是否有子标签 if control.tag in LabelStudioConfigValidator.LABEL_BASED_CONTROLS: labels = control.findall('Label') if not labels: return False, f"{control.tag} must have at least one