XSD: 如何重新定义基本模式的标签
XSD: how to redefine tags of base schema
我必须处理多个 XML 模式才能在 C# 应用程序中验证不同的 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
模式中定义根标签,而不是在基本模式中,因此不需要重新定义,但我当我创建 reader 以验证我的 XML:
时出现此错误
The global element 'http://company.com/myBaseSchema:myRootTag' has already been declared.
我仅使用模式集中的 System.Xml.XmlUrlResolver
解决了 'SchemaLocation' must successfully resolve if <redefine> contains any child other than <annotation>.
问题,以这种方式更改我的加载逻辑:
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;
}
我还删除了 SpecificSchema#.xsd
模式中的 <xs:include>
标签,但在这种情况下它没有任何区别(<xs:redefine>
和 [=20= 的所有其他用法] 元素在有和没有它的情况下都有效。
我必须处理多个 XML 模式才能在 C# 应用程序中验证不同的 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
模式中定义根标签,而不是在基本模式中,因此不需要重新定义,但我当我创建 reader 以验证我的 XML:
The global element 'http://company.com/myBaseSchema:myRootTag' has already been declared.
我仅使用模式集中的 System.Xml.XmlUrlResolver
解决了 'SchemaLocation' must successfully resolve if <redefine> contains any child other than <annotation>.
问题,以这种方式更改我的加载逻辑:
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;
}
我还删除了 SpecificSchema#.xsd
模式中的 <xs:include>
标签,但在这种情况下它没有任何区别(<xs:redefine>
和 [=20= 的所有其他用法] 元素在有和没有它的情况下都有效。