3

我想创建一个 XSD,它定义了一个属性,该属性可以放置在来自其他模式的元素或不在任何模式中的元素上。例如,模式看起来像这样:

<xs:schema id="MySchema"
    targetNamespace="http://tempuri.org/MySchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/MySchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:attribute name="myAttribute" />
</xs:schema>

该文档可能如下所示:

<someElement xmlns="http://tempuri.org/OtherSchema" xmlns:m="http://tempuri.org/MySchema">
  <someOtherElement someAttribute="value" m:myAttribute="value2" />
</someElement>

此示例的“OtherSchema”如下所示:

<xs:schema id="OtherSchema"
    targetNamespace="http://tempuri.org/OtherSchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/OtherSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:element name="someElement">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" name="someOtherElement">
          <xs:complexType>
            <xs:attribute name="someAttribute" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

可以从http://dl.getdropbox.com/u/407740/SchemaTest.zip下载完整的示例,包括执行验证的 C# 控制台应用程序。我的目标是在无需修改“OtherSchema”的情况下进行验证。这可能吗?

4

4 回答 4

1

我必须添加一个包装器,将两个不同的模式导入一个(因为 xmllint 只接受一个 xml 模式):

<xs:schema id="Wrapper" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:import schemaLocation="MySchema.xsd" namespace="http://tempuri.org/MySchema"/>
  <xs:import schemaLocation="OtherSchema.xsd" namespace="http://tempuri.org/OtherSchema"/>
</xs:schema>

我可以让问题之类的东西起作用的唯一方法是编辑 OtherSchema,xsd (问题不允许这样做),因此附加一个属性通配符(在现有通配符之后):

 <xs:attribute name="someAttribute" />
 <xs:anyAttribute namespace="##other"/>

作为 XML Schema 的专家,我还不足以说“这是不可能的”,但对我来说似乎是不可能的。

您的提案的一个问题是您没有指定新属性应出现的位置。通常,如果您声明一个属性(或 complexElement、modelgroup 等),您可以随意引用或不引用它。如果你没有明确地引用它,它就没有效果。因此,我认为您的提案将被视为已声明但未引用的属性。

您真正想要的是一种说“将此属性添加到每个现有的 complexType”的方式 - 但您不会这么说。而且,不幸的是,似乎没有办法这么说。(甚至没有办法说“将此属性添加到这个特定的现有 complexType” - 您必须将其包含在原始定义中或根本不包含。)

部分做到这一点的一种方法是<redefine>输入另一个模式 - 我将在第二个答案中添加它。

于 2009-06-03T18:15:04.953 回答
1

您可以重新定义架构,随心所欲地扩展它们。通过这种方式,您可以修改现有模式的定义,而无需实际更改文件。但它不适用于您给出的示例,因为无法重新定义元素(只有 complexTypes 等,请参阅 http://www.w3.org/TR/xmlschema-1/#element-redefine)。因此,我已将您的示例分解为显式的 complexTypes,以便重新定义它们。

重新定义OtherSchema.xsd:

<xs:schema id="RedefineOtherSchema"
    targetNamespace="http://tempuri.org/OtherSchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/OtherSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:m="http://tempuri.org/MySchema">          <!-- for the ref -->

  <xs:import schemaLocation="MySchema.xsd"
    namespace="http://tempuri.org/MySchema"/>       <!-- import -->

  <xs:redefine schemaLocation="OtherSchema.xsd">    <!-- redefine -->
    <xs:complexType name="SomeOtherElement">
      <xs:complexContent>
        <xs:extension base="SomeOtherElement">
          <xs:attribute ref="m:myAttribute" />      <!-- the ref -->
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:redefine>
</xs:schema>

其他架构:

<xs:schema id="OtherSchema"
    targetNamespace="http://tempuri.org/OtherSchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/OtherSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:element name="someElement" type="SomeElement"/>

    <xs:complexType name="SomeElement">
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded"
                    name="someOtherElement" type="SomeOtherElement"/>
      </xs:sequence>
    </xs:complexType>

    <xs:complexType name="SomeOtherElement">
      <xs:attribute name="someAttribute" />
    </xs:complexType>
</xs:schema>

MySchema:(未更改)

<xs:schema id="MySchema"
    targetNamespace="http://tempuri.org/MySchema"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/MySchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:attribute name="myAttribute"/>
</xs:schema>

为什么<complexContent> 重新定义必须是现有类型的扩展(或限制) - 这就是它修改先前定义的方式。扩展名必须在<complexContent>(我相信)。

为什么<import> 您不能在 xsd 中的多个命名空间中定义事物(只有一个“targetNamespace”)。但是您可以通过从另一个 xsd 导入定义来解决这个问题(然后您没有“定义”它)。【还有其他方法吗?】

HTH :-)

于 2009-06-03T18:38:04.550 回答
0

这正是 NVDL(基于命名空间的验证和调度语言)所提供的。它允许组合多个模式/词汇来验证文档,而无需更改这些模式。NVDL 是一个 ISO 标准。

处理您的案例的工作 NVDL 脚本如下

<rules xmlns="http://purl.oclc.org/dsdl/nvdl/ns/structure/1.0" startMode="other">
  <mode name="other">
    <namespace ns="http://tempuri.org/OtherSchema">
      <validate schema="other.xsd" useMode="validateMyAttributes"/>
    </namespace>
  </mode>
  <mode name="validateMyAttributes">
    <namespace ns="http://tempuri.org/MySchema" match="attributes">
      <validate schema="my.xsd"/>
    </namespace>
  </mode>
</rules>

基本上,它说使用 other.xsd 模式验证 ...tempuri.org/OtherSchema 命名空间上的内容以及使用 my.xsd 模式的 ...tempuri.org/MySchema 中的属性。

有关 NVDL 的更多信息,请参见 www.nvdl.org。上面的脚本是用 oNVDL 测试的。

于 2009-06-04T20:46:26.273 回答
-1

考虑 xsi:nil、xsi:schemaLocation 和 xsi:noNamespaceSchemaLocation。答案是肯定的。

也不会花很长时间去试一试。


您在架构中缺少 targetNamespace。试试这个:

<xs:schema xmlns="MySchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="MySchema">
  <xs:attribute name="myAttribute" />
</xs:schema>
于 2009-05-31T16:25:01.823 回答