如何解决XSD:如何重新定义基本架构的标签
为了验证 C# 应用程序中的不同 XML 文件,我必须处理多个 XML 模式。所有这些 XML 模式都共享一些基本元素,将它们放在一个公共位置而不用每次都重新定义它们会很好。
我的想法是创建一个定义这些通用元素的 BaseSchema.xsd
文件,以及定义特定案例相关元素的其他 SpecificSchema#.xsd
文件。在这些 SpecificSchema#.xsd
架构中,我需要使用基本架构的一些元素,但也需要重新定义根标记。
这是我需要的示例:
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:element name="myRoottag" type="myRoottag" />
<xs:complexType name="myRoottag">
<!-- some content -->
</xs:complexType>
<xs:complexType name="someCommonTag">
<!-- some content -->
</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"/>
<xs:redefine schemaLocation="BaseSchema.xsd">
<xs:complexType name="myRoottag">
<xs:complexContent>
<xs:extension base="myRoottag">
<!-- some content -->
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
<xs:complexType name="someCustomTag">
<xs:sequence>
<!-- some content -->
</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:redefine schemaLocation="BaseSchema.xsd">
<xs:complexType name="myRoottag">
<xs:complexContent>
<xs:extension base="myRoottag">
<!-- some other content different from SpecificSchema1.xsd -->
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
<xs:complexType name="someOtherCustomTag">
<xs:sequence>
<!-- some content -->
</xs:sequence>
</xs:complexType>
</xs:schema>
我需要验证的 XML 文件将是这样的(它们从不引用 BaseSchema.xsd
):
<?xml version="1.0" encoding="utf-16" ?>
<myRoottag xmlns="http://company.com/myBaseSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://company.com/myBaseSchema SpecificSchema1.xsd">
<!-- some content -->
</myRoottag>
显然这似乎有效(所有架构都在同一目录中,并且它们都引用相同的 targetNamespace
),但是当我尝试在 System.Xml.Schema.XmlSchemaSet
中加载所有架构时,它会引发此异常:
'SchemaLocation' must successfully resolve if <redefine> contains any child other than <annotation>.
我还尝试在覆盖架构中引用 BaseSchema.xsd
的完整路径,但没有奏效。
这是我用于架构加载的 C# 代码:
private XmlSchemaSet LoadSchemas()
{
var schemaSet = new XmlSchemaSet();
foreach (var schemaPath in Directory.GetFiles(schemasDirectory))
{
var schema = LoadSchema(schemaPath);
schemaSet.Add(schema);
}
return schemaSet;
}
private XmlSchema LoadSchema(string uri)
{
using (var reader = XmlReader.Create(uri))
{
return XmlSchema.Read(reader,null);
}
}
我做错了什么?
谢谢。
编辑:我还尝试仅在 SpecificSchema#.xsd
架构中而不是在基本架构中定义根标记,因此不需要重新定义,但是当我创建读取器以验证我的 XML:
The global element 'http://company.com/myBaseSchema:myRoottag' has already been declared.
解决方法
我仅在架构集中使用 'SchemaLocation' must successfully resolve if <redefine> contains any child other than <annotation>.
解决了 System.Xml.XmlUrlResolver
问题,以这种方式更改了我的加载逻辑:
private XmlSchemaSet LoadSchemas()
{
var schemaSet = new XmlSchemaSet();
schemaSet.XmlResolver = new System.Xml.XmlUrlResolver(); // this was my missing line
foreach (var schemaPath in Directory.GetFiles(schemasDirectory))
{
var schema = LoadSchema(schemaPath);
schemaSet.Add(schema);
}
return schemaSet;
}
private XmlSchema LoadSchema(string uri)
{
using (var reader = XmlReader.Create(uri))
{
return XmlSchema.Read(reader,null);
}
}
但是将所有模式(基本模式和所有 SpecificSchema#.xsd
模式)一起加载给了我另一个错误:
The complexType 'http://company.com/BaseSchema:myRootTag' has already been declared.
因此,由于我确切地知道必须使用哪个 SpecificSchema#.xsd
,因此我再次更改了加载逻辑,只加载需要的:
private static XmlSchemaSet LoadSchemaSet()
{
var schemaSet = new XmlSchemaSet();
schemaSet.XmlResolver = new System.Xml.XmlUrlResolver();
var schemaPath = schemasDirectory + "\\SpecifiSchema1.xsd";
var schema = LoadSchema(schemaPath);
schemaSet.Add(schema);
return schemaSet;
}
我还删除了 <xs:include>
架构中的 SpecificSchema#.xsd
标记,但在这种情况下它没有任何区别(<xs:redefine>
以及 BaseSchema.xsd
元素的所有其他用法无论有没有它都可以工作)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。