如何在XSD-1.1验证的XML元素中添加自定义属性
不修改原始XSD前提下为XML元素添加自定义属性并通过验证
问题背景
需要在不改动原始.xsd文件的情况下,给经过XSD 1.1验证的XML文档元素添加自定义命名空间属性(如示例中的custom:comment),但使用Python的xmlschema库验证时,会触发如下错误:
Reason: '{http://example.com/custom}comment' attribute not allowed for element
XML示例
<?xml version="1.0" encoding="UTF-8"?> <outer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="root.xsd" > <inner custom:comment="do it now!" xmlns:custom="http://example.com/custom"> <regular id="abc">Content</regular> </inner> </outer>
解决方案
方案1:动态修改加载后的Schema对象
加载原始XSD后,直接修改目标元素的定义,添加允许其他命名空间属性的声明:
import xmlschema # 加载原始XSD文件 schema = xmlschema.XMLSchema('root.xsd') # 定位到需要添加自定义属性的元素(示例中为'inner') target_element = schema.elements['inner'] # 创建任意属性声明,允许所有非目标命名空间的属性,跳过验证 any_attr = xmlschema.XmlSchemaAnyAttribute(namespace='##other', process_contents='skip') # 将该声明添加到元素的属性列表中 target_element.attributes.append(any_attr) # 执行验证,此时自定义属性不会触发报错 schema.validate('your_target.xml')
方案2:使用XSD 1.1的重定义机制创建补丁XSD
创建一个补丁XSD文件,通过xs:redefine扩展原始XSD中的目标元素,允许指定命名空间的自定义属性:
patch.xsd
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:custom="http://example.com/custom" targetNamespace="YOUR_ORIGINAL_TARGET_NAMESPACE" xmlns:tns="YOUR_ORIGINAL_TARGET_NAMESPACE" elementFormDefault="qualified"> <!-- 重定义原始XSD中的元素 --> <xs:redefine schemaLocation="root.xsd"> <xs:element name="inner"> <xs:complexType> <xs:complexContent> <!-- 扩展原始元素的类型,添加自定义命名空间属性的允许规则 --> <xs:extension base="tns:innerType"> <xs:anyAttribute namespace="http://example.com/custom" processContents="skip"/> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> </xs:redefine> </xs:schema>
替换YOUR_ORIGINAL_TARGET_NAMESPACE为原始XSD的目标命名空间(如果原始XSD无命名空间,可删除相关命名空间声明)。
然后加载补丁XSD进行验证:
import xmlschema schema = xmlschema.XMLSchema('patch.xsd') schema.validate('your_target.xml')
方案3:自定义属性验证逻辑
直接替换元素的属性验证方法,过滤掉自定义命名空间的属性后再执行原始验证:
import xmlschema from xmlschema.validators import XsdElement def custom_attr_validation(self, attrs, context): # 过滤掉custom命名空间下的所有属性 filtered_attrs = { attr_name: attr_value for attr_name, attr_value in attrs.items() if not attr_name.startswith('{http://example.com/custom}') } # 调用原始的属性验证方法 return self._original_validate_attributes(filtered_attrs, context) # 加载原始Schema schema = xmlschema.XMLSchema('root.xsd') target_element = schema.elements['inner'] # 保存原始验证方法,替换为自定义逻辑 target_element._original_validate_attributes = target_element._validate_attributes target_element._validate_attributes = custom_attr_validation.__get__(target_element, XsdElement) # 执行验证 schema.validate('your_target.xml')
内容的提问来源于stack exchange,提问作者towi
相关产品推荐
相关产品推荐

