1

简而言之,问题是“我可以在可以整体验证的模式中定义一个模式吗?

解释:

是否可以为以下 XML 定义模式。我需要为“客户”定义一个模式。“customertype”子元素本身就是一个模式。在 customertype 中,我应该有一个名为“Source”的元素,这是强制性的。

 <customer>
    <customername>acustomer</customername>
    <customertype>
      <xs:schema>
      <xs:element name="profession">
         <xs:complexType>
              <xs:sequence>
                 <xs:element name="Source" type="xs:int" />
                 <xs:element name="ProfessionName" type="xs:string" />
             </xs:sequence>
          </xs:complexType>     
         </xs:schema>
      </customertype>
  </customer>

是否可以定义此 xml 的架构以满足所有要求?

4

2 回答 2

2

正如 Mimo 所指出的,将 customertype(或另一个其他元素)定义为包含 XSD 名称空间中的元素是没有问题的,这似乎就是您要问的问题。

但是,如果您的目标是能够验证客户元素(或职业元素,这是您示例中的架构所声明的),那么很难想象一个验证架构是最好的方式(甚至是可行的方式)去关于它。一个原因是,根据正在验证的实例提供的模式信息验证文档实例不会产生与根据已知模式验证数据相同的信心。(将自己置于一个试图破坏您的验证并说服您的系统接受虚假数据为有效的对手的立场。如果对手指定什么是有效的文档实例,那么知道该文档是有效的有多大用处?)

是什么阻止您编写模式并以通常的方式使用它?

[添加,2012 年 10 月 15 日,在 OP 评论之后]

如果我正确理解了您今天早些时候的评论,您的要求是允许除您以外的人指定 customer他们喜欢的元素类型,但条件是该类型必须包含一个名为 Source 的子元素,其类型将是xsd:int。您没有指定是否需要访问他们正在使用的类型定义,因此我将尝试考虑您确实需要它的情况和您不需要它的情况。

下面描述了使这种情况起作用的三种方法。他们的共同点是

  • 定义模式基本版本的“主”模式文档,以及
  • 用于不同情况的一个或多个“辅助”模式文档。

一般来说,您可能会发现找到一本关于 XSD 的好教科书并查看它关于从多个模式文档中的声明创建模式的内容会很有帮助。

(1) 一种方法使用xsi:type. 您定义一个主模式文档,其中customer元素具有命名类型;我假设类型是命名的Customer。该Customer类型接受其第一个子元素名为 的任何元素Source。例如:

<xs:element name="customer" type="Customer"/>
<xs:complexType name="Customer">
  <xs:sequence>
    <xs:element name="Source" type="xs:int"/>
    <xs:any minOccurs="0" 
            maxOccurs="unbounded" 
            processContents="lax"/>
  </xs:sequence>
  <xs:anyAttribute processContents="lax"/>
</xs:complexType>

那些想要customer元素更具体类型的人(我称他们为“用户”)为您的目标命名空间提供辅助模式文档,他们在其中声明了其他复杂的类型限制Customer。例如,他们可能希望customer元素包含名为姓名、地址和电话号码的元素:

<xs:complexType name="Customer-for-us">
  <xs:complexContent>
    <xs:restriction base="Customer">
      <xs:sequence>
        <xs:element name="Source" type="xs:int"/>
        <xs:element ref="name"/>
        <xs:element ref="address"/>
        <xs:element ref="phone"/>
      </xs:sequence>
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

这是 Customer 类型的法律限制,因此customer元素可以使用它。因此,文档实例可能包含如下元素:

<customer xsi:type="Customer-for-us">
  <Source>83760273</Source>
  <name>Willy Wonka</name>
  <address> ... </address>
  <phone> ... </phone>
</customer>

该文档根据从其辅助模式文档以及主模式文档构造的模式进行验证,因此以Customer-for-us通常的方式强制执行类型的定义。

通过使用通配符和宽松的验证,客户类型确保用户可以在他们的类型版本中做任何他们喜欢的事情,只要第一个孩子被命名为 Source 并且具有 int 类型。

(2) 第二种方法在主模式文档中使用了一个漏洞。

您像以前一样编写主模式文档,包括将customer元素声明为具有 type Customer。但是主模式文档不包含该类型的声明。相反,您在辅助模式文档中声明 Customer 类型,该类型在验证时以通常的方式与主要模式文档结合(我建议您使用第三个模式文档作为驱动程序并包含其他两个,但是有很多方法可以让它工作)。

同时,需要更具体的 Customer 类型的用户为 Customer 类型编写自己的声明,受制于名为 Source 的第一个子类型的兼容性约束,依此类推。用户使用他们自己的驱动程序文件,该文件将主模式文档和他们的辅助模式文档版本与他们自己的客户类型声明一起嵌入。

这样,xsi:type就不需要使用该属性。

(3) 第三种方法使用xs:redefine或(在 XSD 1.1 中)xs:override工具。

您按照解决方案 (1) 中的描述编写主模式文档。用户根据需要使用xs:redefinexs:override重新定义客户。这个答案已经很长了,所以我不建议包含有关使用重新定义或覆盖的教程。

于 2012-10-12T17:10:09.567 回答
1

可以创建导入和使用另一个模式的模式。这定义了包含架构的customer元素:customertype

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://xml.netbeans.org/schema/Notes"
            xmlns:tns="http://xml.netbeans.org/schema/Notes"
            elementFormDefault="qualified">

  <xsd:import namespace="http://www.w3.org/2001/XMLSchema"/>

  <xsd:element name="customer">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="customername" type="xsd:string"/>
        <xsd:element name="customertype">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element ref="xsd:schema"/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

问题是你对customertype模式有一个额外的条件——所以理论上你应该得到标准的 XSD 模式并修改它,但是在模式定义中有很多不同的方法可以满足这个条件,所以它非常棘手(也许不可能)做这个“修改”

可能更好的方法是限制内部使用的可能模式customertype(例如,它必须是直接指定复杂类型的单个元素定义等)并编写描述此受限模式定义的 XSD 模式的子集。

于 2012-10-10T23:02:55.600 回答