如何用Python的Pydantic-XML生成带有序前缀的XML命名空间?
解决方案:生成带指定前缀命名空间的XML
你需要生成带ns1/ns2/ns3前缀的命名空间XML,当前Pydantic-XML生成的是默认命名空间,可通过以下两种方式实现需求:
方法一:调整Pydantic-XML模型配置
原代码的问题在于每个子模型单独声明默认命名空间,导致每个元素都重复声明命名空间。正确的做法是在根模型统一声明所有命名空间的前缀映射,子元素通过ns参数关联对应前缀:
from typing import List from pydantic_xml import BaseXmlModel, element class Socials(BaseXmlModel, tag='socials'): urls: List[str] = element(tag='social', ns='ns3') class Contacts(BaseXmlModel, tag='contacts'): socials: Socials = element(ns='ns3') class Company(BaseXmlModel, tag='company', ns='ns1', nsmap={ 'ns1': 'http://www.company.com/co', 'ns2': 'http://www.company.com/cnt', 'ns3': 'http://www.company.com/soc' }): contacts: Contacts = element(ns='ns2') # 测试生成XML company = Company( contacts=Contacts( socials=Socials( urls=[ "https://www.linkedin.com/company/spacex", "https://twitter.com/spacex", "https://www.youtube.com/spacex" ] ) ) ) print(company.to_xml(pretty_print=True))
生成的XML会在根元素统一声明所有命名空间,子元素使用对应前缀,符合业务要求。
注意:你给出的期望输出中,
social元素的闭合标签前缀有误,正确应为</ns3:social>而非</ns2:social>。
方法二:用lxml结合Pydantic(灵活控制XML结构)
如果Pydantic-XML的命名空间配置无法满足需求,可先通过Pydantic验证数据,再用lxml手动构建XML,完全控制命名空间格式:
from typing import List from pydantic import BaseModel from lxml import etree # Pydantic数据模型,用于验证输入 class SocialsModel(BaseModel): urls: List[str] class ContactsModel(BaseModel): socials: SocialsModel class CompanyModel(BaseModel): contacts: ContactsModel # 验证输入数据 data = { "contacts": { "socials": { "urls": [ "https://www.linkedin.com/company/spacex", "https://twitter.com/spacex", "https://www.youtube.com/spacex" ] } } } validated_data = CompanyModel(**data) # 构建XML结构 ns_map = { 'ns1': 'http://www.company.com/co', 'ns2': 'http://www.company.com/cnt', 'ns3': 'http://www.company.com/soc' } # 创建根元素并声明所有命名空间前缀 root = etree.Element('{http://www.company.com/co}company', nsmap=ns_map) # 添加contacts子元素 contacts_elem = etree.SubElement(root, '{http://www.company.com/cnt}contacts') # 添加socials子元素 socials_elem = etree.SubElement(contacts_elem, '{http://www.company.com/soc}socials') # 逐个添加social元素 for url in validated_data.contacts.socials.urls: social_elem = etree.SubElement(socials_elem, '{http://www.company.com/soc}social') social_elem.text = url # 格式化输出XML xml_output = etree.tostring(root, pretty_print=True, encoding='unicode') print(xml_output)
这种方式不受Pydantic-XML的限制,可完全自定义XML的命名空间和标签格式。
内容的提问来源于stack exchange,提问作者dksr
相关产品推荐
相关产品推荐

