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

如何为Python的ElementTree创建自定义Pydantic类型

解决Pydantic自定义ElementTree.Element类型的问题

问题出在ElementTree.Element并非Pydantic原生支持的类型,直接用Annotated无法让Pydantic自动识别其转换逻辑。以下是两种可行的实现方案:

方案一:使用Annotated + 前置验证器

通过BeforeValidator指定自定义解析函数,实现字符串到ET.Element的转换,并处理XML解析错误:

import xml.etree.ElementTree as ET
from pydantic import BaseModel, BeforeValidator, ValidationError, Annotated

def parse_xml(xml_str: str) -> ET.Element:
    try:
        return ET.fromstring(xml_str)
    except ET.ParseError as e:
        # 抛出Pydantic可识别的验证错误
        raise ValueError(f"无效的XML格式:{str(e)}") from e

# 定义自定义Annotated类型
XmlElement = Annotated[ET.Element, BeforeValidator(parse_xml)]

# 使用自定义类型的模型
class XmlModel(BaseModel):
    content: XmlElement

# 测试用例
if __name__ == "__main__":
    # 有效XML
    valid_xml = "<root><item>test</item></root>"
    model = XmlModel(content=valid_xml)
    print(model.content.tag)  # 输出: root

    # 无效XML
    invalid_xml = "<root><item>test</root>"
    try:
        XmlModel(content=invalid_xml)
    except ValidationError as e:
        print(e)  # 输出包含XML解析错误的验证信息

方案二:自定义Pydantic类型类

如果需要在多个地方复用这个类型,推荐创建自定义类型类,直接实现Pydantic的核心schema逻辑:

import xml.etree.ElementTree as ET
from pydantic import BaseModel, ValidationError
from pydantic_core import core_schema
from pydantic import GetCoreSchemaHandler
from typing import Any

class XmlElement(ET.Element):
    @classmethod
    def __get_pydantic_core_schema__(
        cls, source_type: Any, handler: GetCoreSchemaHandler
    ) -> core_schema.CoreSchema:
        # 定义schema规则:接受字符串输入,通过验证器转换为Element
        return core_schema.no_info_wrap_validator_function(
            cls._validate_xml,
            core_schema.str_schema(),
        )
    
    @classmethod
    def _validate_xml(cls, value: str) -> ET.Element:
        try:
            return ET.fromstring(value)
        except ET.ParseError as e:
            raise ValueError(f"XML解析失败:{str(e)}") from e

# 使用自定义类型的模型
class XmlModel(BaseModel):
    content: XmlElement

# 测试用例
if __name__ == "__main__":
    valid_xml = "<root><item>test</item></root>"
    model = XmlModel(content=valid_xml)
    print(model.content.find("item").text)  # 输出: test

    invalid_xml = "<root><item>test"
    try:
        XmlModel(content=invalid_xml)
    except ValidationError as e:
        print(e)

两种方案的核心都是:显式告诉Pydantic如何将输入字符串转换为ET.Element,并捕获解析错误转为Pydantic验证错误。方案一更轻量,适合单次使用;方案二更适合作为可复用的类型组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 20:23:23