架构中的XML架构

时间:2012-10-10 18:14:38

标签: xsd

简而言之 - “我可以在架构中定义一个可以作为整体验证的架构吗?

说明:

是否可以为以下XML定义架构。我需要为“客户”定义架构。 “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定义架构以满足所有要求?

2 个答案:

答案 0 :(得分:2)

正如Mimo指出的那样,将customertype(或其他元素)定义为包含XSD名称空间中的元素没有问题,这就是您要求的内容。

但是如果您的目标是能够验证客户元素(或职业元素,这是您的示例中的模式声明的那些元素),那么很难想象验证体系结构,这是最好的方式(甚至是可行的方式)去做吧。一个原因是根据被验证的实例提供的模式信息验证文档实例对数据的清洁度不会产生与对已知模式进行验证相同的信心。 (让自己陷入敌人的境地,试图颠覆你的验证并说服你的系统接受伪造的数据是有效的。如果对手得到指明什么算作有效的文档实例,那么知道文档有效是多么有用?)

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

[另外,2012年10月15日,OP发表评论后]

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

使这种情况发挥作用的三种方法如下所述。他们的共同点是

  • 定义架构基本版本的“主”架构文档,
  • 一个或多个“辅助”架构文档,供不同情况使用。

一般情况下,您可能会发现在XSD上找到一本好的教科书并查看有关从多个架构文档中的声明创建架构的内容是有帮助的。

(1)一种方法使用xsi:type。您可以定义一个主模式文档,其中customer元素具有命名类型;我假设类型名为CustomerCustomer类型接受其第一个子元素名为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元素的更具体类型的人(我将其称为'用户')为目标命名空间提供辅助模式文档,在这些文档中,它们声明了限制{{1}的其他复杂类型}。例如,他们可能希望Customer元素包含名为name,address和phone number的元素:

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 xsi:type="Customer-for-us"> <Source>83760273</Source> <name>Willy Wonka</name> <address> ... </address> <phone> ... </phone> </customer> 的定义以通常的方式强制执行。

通过使用通配符和宽松验证,Customer类型可确保用户可以在其类型的版本中执行任何操作,只要第一个子项名为Source且类型为int。

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

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

同时,想要更具体的Customer类型的用户为Customer类型编写自己的声明,但要遵守有关名为Source的第一个子项的兼容性限制,依此类推。用户使用自己的驱动程序文件,该文件将主模式文档及其辅助模式文档的版本与其自己的Customer类型声明嵌入。

这样,不需要使用Customer属性。

(3)第三种方法使用xsi:type或(在XSD 1.1中)xs:redefine设施。

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

答案 1 :(得分: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模式的子集。限制模式定义。