微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

XSD:如何重新定义基本架构的标签

如何解决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 举报,一经查实,本站将立刻删除。