IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  XML  >

用于数据的 XML: 使用 XML Schema 原型

将原型的表单添加到 XML Schema 中

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

Kevin Williams (kevin@realworldxml.com), 首席 XML 设计师, Equient(Veridian 的一个部门)

2001 年 6 月 01 日

在 Kevin Williams 的新专栏的第一部分中,他描述了 在用于数据的 XML Schema 设计中使用原型的好处并且提供了一些具体示例。 他讨论了简单类型和复杂类型以及使用每种类型的优势。提供了 XML Schema 中的代码样本。

在我的“Soapbox”(请参阅 参考资料)专栏文章中,我顺便提到了 如何在用于数据的 XML Schema 设计中使用原型以显著地将项目所需的编码和维护工作减到最小,并减少剪贴错误的 可能性。在本专栏中,我将给出在用于数据的 XML Schema 中使用原型的一些示例,并显示好处何在。

什么是原型?

原型是 XML Schema 中可以跨越不同元素共享的公共定义。在 XML Schema 规范的早期版本中, 原型具有其自己的声明;然而,在发行版中,原型是使用 simpleTypecomplexType 元素 实现的。让我们讨论一下每种情况的示例。





回页首


简单原型

简单原型是通过扩展由 XML Schema 提供的内置数据类型创建的。该类型的可允许值可能 由所谓 来限制,面是可能为每个内置数据类型设置的不同参数的非常漂亮的术语。还有可能 通过定义两种其它数据类型的联合体或通过创建对应于某些其它数据类型的值列表来创建一个简单类型。但是, 为了实现我们的目的,简单类型的限制性声明是最有趣的。让我们看一下某些示例。

假定在关系数据库中有一个描述贷款的表,如“清单 1”所示。


清单 1. 贷款表声明
CREATE TABLE loan (
  loanID INT IDENTITY,
  duration SMALLINT,
  initialBalance DECIMAL(10, 2),
  currentBalance DECIMAL(10, 2),
  interestRate DECIMAL(5, 2))

显然,这些值直接映射成 XML Schema 中的内置数据类型,所以 在目标模式中可以仅将元素声明为匿名 simpleType 元素并一定要这样做。但是, 定义一些简单原型来使用也是很有意义的。让我们看一下原因所在。

使用数据原型的好处?

  • 需要更少的代码
  • 简化了维护和更新
  • 减少了发生剪贴错误的可能性

一致性

在示例中使用原型的最明显原因是两个余额字段都表达了相似的概念 - 货币值 - 并且它们是 用同一方法声明的。设计关系数据库时,要确保都用同一方法定义这些字段可能是件很痛苦的事。假设的 示例数据库甚至可能定义一个称为 Balance的用户类型,它被定义成带有 10 位有效数字的十进制数并且 小数点后有 2 位。在 XML Schema 中应该使用同一精度定义类型。这将使模式更具可读 性 - 一种明智命名的数据类型表达了有关正在描述的数据类型的信息 - 并确保整个模式中的 一致性(尝试将 decimal(10, 2) 存储到声明为 decimal(9, 2) 的字段中也不会有更多问题)。同样, 如果定义了一次原型表单并且在从数据中产生的所有模式中使用它们, 则可以简化编写可以处理创建的所有模式的用户过程。每次用户过程需要处理 来自 OurCompany 的文档,可以确保将用同一方法定义所有货币值。

缩减的编码

如果定义了一次原型并在任何需要的地方重用它们,则可以显著地减小模式的大小。例如, 假定定义了保存前面指的 SQL 表中的两个余额字段的元素。可以用匿名简单类型定义数据元素, 如“清单 2”所示。


清单 2. 使用匿名简单类型
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="loan">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="initialBalance">
          <xs:simpleType>
            <xs:restriction base="xs:decimal">
              <xs:totalDigits value="10" />
              <xs:fractionDigits value="2" />
            </xs:restriction>
          </xs:simpleType>
        </xs:element>
        <xs:element name="currentBalance">
          <xs:simpleType>
            <xs:restriction base="xs:decimal">
              <xs:totalDigits value="10" />
              <xs:fractionDigits value="2" />
            </xs:restriction>
          </xs:simpleType>
        </xs:element>
      </xs:sequence>      
    </xs:complexType>
  </xs:element>
</xs:schema>

“清单 2”中的代码看起来很好,但是如果遇到严重的通货膨胀并且 需要将贷款上限从 1 亿美元改为 100 亿美元时,将会发生什么呢?您不得不在声明余额的每个地方更改 它,这当然是自找麻烦。但是,可以对余额改为使用一个命名的简单原型作法,如“清单 3”所示。


清单 3. 使用简单类型原型
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="loan">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="initialBalance" type="balance" />
        <xs:element name="currentBalance" type="balance" />
      </xs:sequence>      
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="balance">
    <xs:restriction base="xs:decimal">
      <xs:totalDigits value="10" />
      <xs:fractionDigits value="2" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

在“清单 3”中,使用命名的简单原型的优势是显而易见的。模式声明更短(即使 挤压掉空格,仍然比原来小大约 30 个字节),并且使模式定义更加易于管理。另外, 如果那个大通货膨胀突然出现(由于不合理的减税或某些其它荒唐的原因), 处理更大规模贷款的规范更改涉及更改一个声明,即 balance 简单类型。





回页首


复杂原型

对于复杂原型的重用问题,可以应用相同的逻辑。假定在制造数据库中有一个顾客表。该表部分地 可能会,如同“清单 4”。


清单 4. 顾客表声明
CREATE TABLE customer (
  customerID int IDENTITY,
  mailingAddress varchar(50),
  mailingAddress2 varchar(50) NULL,
  mailingCity varchar(30),
  mailingState char(2),
  mailingZip char(10),
  shippingAddress varchar(50),
  shippingAddress2 varchar(50) NULL,
  shippingCity varchar(30),
  shippingState char(2),
  shippingZip char(10))

同样,您有几种选择:可以将所有这些字段声明为简单类型,或者可以创建地址复杂原型 并在需要的地方重用。让我们看看在“清单 5”中将如何完成该任务。


清单 5. 不带复杂类型的代码样本
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="customer">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="mailingAddress"> 
          <xs:complexType> 
            <xs:sequence>
              <xs:element name="address">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="50" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="address2" minOccurs="0">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="50" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="city">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="30" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="state">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:length value="2" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="zip">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="10" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="shippingAddress"> 
          <xs:complexType>
            <xs:sequence>
              <xs:element name="address">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="50" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="address2" minOccurs="0">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="50" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="city">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="30" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="state">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:length value="2" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="zip">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="10" />
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>       

哎呀!我是否提到过该模式会有点绕吗?以“清单 5”为例,一种明显的替代 方法出现了 - 创建 address 复杂原型。如果这样做,模式将变得更短一点,如“清单 6”所示。


清单 6. 带有复杂类型的代码样本
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="customer">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="mailingAddress" type="addressType" /> 
        <xs:element name="shippingAddress" type="addressType" /> 
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="addressType">
    <xs:sequence>
      <xs:element name="address">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="50" />
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="address2" minOccurs="0">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="50" />
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="city">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="30" />
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="state">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:length value="2" />
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="zip">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="10" />
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

再次,我提交的“清单 6”中的版本更简短,并且更易于理解。将本示例与事实相结合可以引进更多原 型,例如 addressaddress2 元素使用的地址 行的简单原型,而且可以发现正确使用原型如何帮助使模式变得可管理。





回页首


结束语

本部分讲述了XML 模式设计中原型的使用。您已经看到明智的使用原型,加上巧妙的命名约定,可以 使模式更短并更易于维护。使用原型还有一个好处 - 确保信息样式一致的小窍门 - 但是,这是另一 部分的主题了(很快就会看到)。



参考资料



关于作者

Kevin Williams 是 Equient 的 首席 XML 设计师,Equient 是 Veridian 专门从事信息管理系统的 XML 设计的一个部门。他还 与人合著了几本关于 XML 的书籍,由 Wrox Press 出版。可通过 kevin@realworldxml.com与他联系以获取说明。“万能”钥匙在哪里呢?




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款