C#应用中使用XSD redefine重定义基架构标签时XmlSchemaSet加载异常及根标签重复声明问题
问题分析与解决方案
首先得指出你踩的两个关键坑:同时使用<xs:include>和<xs:redefine>,以及把所有Schema一次性加载到同一个XmlSchemaSet里,这两个操作直接导致了你遇到的异常。下面一步步给你拆解并修正:
1. 移除重复的<xs:include>,正确使用<xs:redefine>
你在SpecificSchema#.xsd里同时写了<xs:include>和<xs:redefine>,但<xs:redefine>本身就具备导入基Schema内容的能力,额外的<xs:include>会造成重复导入,触发Schema解析时的路径和重复定义问题。
修改后的SpecificSchema1.xsd应该去掉<xs:include>:
<?xml version="1.0" encoding="utf-8"?> <xs:schema id="SpecificSchema1" targetNamespace="http://company.com/myBaseSchema" elementFormDefault="qualified" xmlns="http://company.com/myBaseSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- 只保留redefine,它会自动导入BaseSchema的内容 --> <xs:redefine schemaLocation="BaseSchema.xsd"> <xs:complexType name="myRootTag"> <xs:complexContent> <xs:extension base="myRootTag"> <!-- SpecificSchema1的自定义内容 --> </xs:extension> </xs:complexContent> </xs:complexType> </xs:redefine> <xs:complexType name="someCustomTag"> <xs:sequence> <!-- 自定义内容 --> </xs:sequence> </xs:complexType> </xs:schema>
SpecificSchema2.xsd做同样的修改即可。
2. 避免根元素重复声明:调整Schema结构
如果你尝试不在基Schema里定义根元素,又会遇到重复声明错误,本质是因为两个SpecificSchema都在同一个命名空间下定义了myRootTag元素,而你把所有Schema都塞进了同一个XmlSchemaSet。
更合理的结构应该是:
- BaseSchema只定义公共类型,不定义根元素
- 每个
SpecificSchema通过<xs:include>导入基Schema,然后定义自己的根元素(使用不同的类型名来继承基类)
修改后的BaseSchema.xsd
<?xml version="1.0" encoding="utf-8"?> <xs:schema id="BaseSchema" targetNamespace="http://company.com/myBaseSchema" elementFormDefault="qualified" xmlns="http://company.com/myBaseSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- 只保留公共复杂类型,不定义根元素 --> <xs:complexType name="myRootBaseType"> <!-- 基础内容 --> </xs:complexType> <xs:complexType name="someCommonTag"> <!-- 公共内容 --> </xs:complexType> </xs:schema>
修改后的SpecificSchema1.xsd
<?xml version="1.0" encoding="utf-8"?> <xs:schema id="SpecificSchema1" targetNamespace="http://company.com/myBaseSchema" elementFormDefault="qualified" xmlns="http://company.com/myBaseSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:include schemaLocation="BaseSchema.xsd"/> <!-- 定义专属的根元素,类型继承基类的myRootBaseType --> <xs:element name="myRootTag" type="myRootTagType1"/> <xs:complexType name="myRootTagType1"> <xs:complexContent> <xs:extension base="myRootBaseType"> <!-- SpecificSchema1的自定义内容 --> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="someCustomTag"> <xs:sequence> <!-- 自定义内容 --> </xs:sequence> </xs:complexType> </xs:schema>
修改后的SpecificSchema2.xsd
<?xml version="1.0" encoding="utf-8"?> <xs:schema id="SpecificSchema2" targetNamespace="http://company.com/myBaseSchema" elementFormDefault="qualified" xmlns="http://company.com/myBaseSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:include schemaLocation="BaseSchema.xsd"/> <!-- 定义专属的根元素类型 --> <xs:element name="myRootTag" type="myRootTagType2"/> <xs:complexType name="myRootTagType2"> <xs:complexContent> <xs:extension base="myRootBaseType"> <!-- SpecificSchema2的自定义内容 --> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="someOtherCustomTag"> <xs:sequence> <!-- 自定义内容 --> </xs:sequence> </xs:complexType> </xs:schema>
3. 调整C#加载逻辑:按需加载Schema集合
不能把所有Schema都加载到同一个XmlSchemaSet里,因为两个SpecificSchema定义了同命名空间下的同名根元素,会触发重复声明错误。应该根据要验证的XML对应的Schema,加载对应的SpecificSchema和BaseSchema:
// 根据目标Schema文件名加载对应的Schema集合 private XmlSchemaSet LoadTargetSchemaSet(string specificSchemaFileName) { var schemaSet = new XmlSchemaSet(); string baseSchemaPath = Path.Combine(schemasDirectory, "BaseSchema.xsd"); string specificSchemaPath = Path.Combine(schemasDirectory, specificSchemaFileName); // 先加载基Schema schemaSet.Add(LoadSchema(baseSchemaPath)); // 再加载对应的SpecificSchema schemaSet.Add(LoadSchema(specificSchemaPath)); // 编译并返回 schemaSet.Compile(); return schemaSet; } private XmlSchema LoadSchema(string uri) { using (var reader = XmlReader.Create(uri)) { return XmlSchema.Read(reader, (sender, args) => { // 捕获Schema加载错误 if (args.Severity == XmlSeverityType.Error) { throw new InvalidOperationException($"Schema加载失败:{args.Message}"); } }); } }
比如验证引用SpecificSchema1.xsd的XML时,调用LoadTargetSchemaSet("SpecificSchema1.xsd")即可。
内容的提问来源于stack exchange,提问作者maradev21
相关产品推荐
相关产品推荐

