当前位置: 首页 > 工具软件 > XSD/e > 使用案例 >

xsd 两个xsd整合_使用多态替代xsd:choice

柳墨一
2023-12-01

xsd 两个xsd整合

xsd:choice是一种较为常见的XML构造。 但是,将xsd:choice映射到编程语言并不总是那么简单。 例如,JAX-RPC规范定义的Web服务的Java映射没有提供从xsd:choice到Java的显式映射。 每当JAX-RPC代码生成器在类型定义中遇到xsd:choice时,它都会将该类型映射到javax.xml.soap.SOAPElementSOAPElement是SAAJ API的一部分,它不是一个非常用户友好的API。

您可以采取一些措施以获得更好的API。 如果您能够更改XML模式,一个不错的选择是用多态替换xsd:choice

比较xsd:choice和多态

多态性的意思是“许多形状”。 例如,可以使用基本类型声明方法参数。 调用该方法时,该参数的实例是该类型的特定扩展。

您可以类似地描述xsd:choice 。 可以使用描述所有可能选择的类型声明方法参数。 调用该方法时,该参数的实例将包含特定的选择。

实际的单词是不同的,但是它们的含义本质上是相同的。

将简单的xsd:choice类型映射为多态类型

要将典型选择类型转换为一组多态类型,需要在给定选择类型C下执行以下操作,其中包含选择c1..cn:

  1. 构建包含C的那些元素(不是选择元素)的抽象类型P
  2. 对于c1..cn中的每个c,构建E of P的扩展类型E of P其中包含c的元素。

用示例理解概念总是比较容易的。 看一下付款选项的声明。 清单1是选择类型。 清单2是对一组多态类型的转换。

清单1.选择付款
<complexType name="Payment">
  <sequence>
    <element name="amount" type="int"/>
    <choice>
      <element name="cash" nillable="true" type="string"/>
      <element name="check" type="tns:Check"/>
      <element name="credit" type="tns:Credit"/>
    </choice>
  </sequence>
</complexType>

<complexType name="Check">
  <sequence>
    <element name="checkNo" type="int"/>
  </sequence>
</complexType>
<complexType name="Credit">
  <sequence>
    <element name="cardNo" type="string"/>
    <element name="expiration" type="date"/>
  </sequence>
</complexType>
清单2.多态支付
<complexType abstract="true" name="Payment">
  <sequence>
    <element name="amount" type="int"/>
  </sequence>
</complexType>

<complexType name="CashPayment">
  <complexContent>
    <extension base="tns:Payment">
      <sequence>
        <element name="cash" nillable="true" type="string"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

<complexType name="CheckPayment">
  <complexContent>
    <extension base="tns:Payment">
      <sequence>
        <element name="check" type="tns:Check"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

<complexType name="CreditPayment">
  <complexContent>
    <extension base="tns:Payment">
      <sequence>
        <element name="credit" type="tns:Credit"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

多态支付示例比选择支付示例更为冗长。 这是因为XML并不是真正的面向对象的语言,并且将面向对象的功能应用于它并不是一件容易的事。 但这不应该阻止您。 您很可能会将XML映射到编程语言。 作为使用该特定编程语言的开发人员,您无需关心XML模式的外观。 您只需要关心该模式的语言映射是什么样。

唯一需要关心XML模式外观的时间是当您想要进行性能分析时。 例如,如果此架构是Web服务的一部分,则要比较这些类型的简单对象访问协议(SOAP)消息,以确定消息大小本身是否影响性能。 因此,让我们比较这两个变体的实例。 例如,假设我们希望以支票(1050号)付款,金额为10美元。 清单3显示了选择示例,清单4显示了多态示例。 (请注意,为了简化此示例,我忽略了名称空间和前缀。)

清单3.选择付款实例
<payment>
  <amount>10</amount>
  <check>
    <checkNo>1050</checkNo>
  </check>
</payment>
清单4.多态支付实例
<payment xsi:type="CheckPayment">
  <amount>10</amount>
  <check>
    <checkNo>1050</checkNo>
  </check>
</payment>

如您所见,清单4和清单5之间的唯一区别是多态实例包含类型信息。 尽管这值得注意,但通常并不重要。 实际上,它可以潜在地简化SOAP引擎的处理,因为该引擎从一开始就知道类型是什么,并预先选择了合适的反序列化器,而不必解析实例并检查choice元素的名称- -在这种情况下, check -确定类型。

因此,使用多态替代并不比选择替代昂贵得多,它可以为您提供更加友好的语言映射。

映射xsd:choice maxOccurs大于1的xsd:choice

绝大多数选择方案与上面显示的简单情况相似。 但choice 可能具有maxOccurs属性大于1 。 映射是相似的,但是您需要一个额外的层来处理这种新类型的新数组方面。

  1. 建立一个空的抽象类型P
  2. 用类型为P的元素替换C中的选择,并携带从选择到新元素的maxOccurs属性。
  3. 对于c1..cn中的每个c,构建P的扩展类型E ,其中包含c的元素。

例如,修改清单1中的Payment类型,以在选择项上包含maxOccurs="unbounded"属性。 (请参见清单5,其中的附加内容以粗体突出显示。)

(此类型的意思是一个人可以使用多种付款方式进行单笔付款:部分现金,部分支票,部分信用卡或任何组合。)

清单5.具有maxOccurs选择付款
<complexType name="Payment">
  <sequence>
    <element name="amount" type="int"/>
    <choice maxOccurs="unbounded">
      <element name="cash" nillable="true" type="string"/>
      <element name="check" type="tns:Check"/>
      <element name="credit" type="tns:Credit"/>
    </choice>
  </sequence>
</complexType>

清单6显示了转换后的多态类型集。 清单2中的更改以粗体突出显示。

清单6. maxOccurs多态支付
<complexType name="Payment">
  <sequence>
    <element name="amount" type="int"/>
    <element name="option" type="PaymentOption" maxOccurs="unbounded"/>
  </sequence>
</complexType>

<complexType abstract="true" name="PaymentOption">
  <sequence/>
</complexType>


<complexType name="CashPayment">
  <complexContent>
    <extension base="tns:PaymentOption">
      <sequence>
        <element name="cash" nillable="true" type="string"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

<complexType name="CheckPayment">
  <complexContent>
    <extension base="tns:PaymentOption">
      <sequence>
        <element name="check" type="tns:Check"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

<complexType name="CreditPayment">
  <complexContent>
    <extension base="tns:PaymentOption">
      <sequence>
        <element name="credit" type="tns:Credit"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

请注意, PaymentOption类型没有自己的字段。 可能看起来有些奇怪,但是没有任何问题。 这是一种抽象类型,因此PaymentOption实例将永远不存在。 只有它的扩展名可以存在。

请注意,您还可以应用maxOccurs规则来转换典型选择示例。 但是,我希望您能看到简化的规则对典型情况的好处:您可以处理的间接层少了,类型少了一种。

多态性优于xsd:choice优势

xsd:choice相比,多态有两个主要优点xsd:choice :可扩展性和类型指示。

可扩展性

就其性质而言,多态类型是可扩展的。 您可以根据需要选择任意数量的抽象基本类型扩展名,具体取决于您是否出于组织目的将这些扩展名扩展到多个.xsd文件中(一个组织可能仅接受现金和支票;另一个组织可能仅接受信用卡和在线支付)或者是否随着时间的推移添加新的。

但是xsd:choice本身是不可扩展的。 如果要随时间添加选择,或者要在不同的.xsd文件中选择不同的选择集,则要么将所有可能的选择都定义为一个整体类型,然后让代码担心每种情况下可用的内容,要么您有很多选择包含相同选择选项的类型。 这些选项都不是特别可靠。 确实可以扩展选择类型并向扩展类型添加选择,但是为什么不进行全面的跨越并完全遵循多态模式,从而删除所有xsd:choice用法?

类型指示

在此付款示例中,选择之一是cash 。 您是否注意到这似乎是一个定义很奇怪的选择? 除了金额外,您还需要了解现金吗? 没有。 这就是为什么添加了属性nillable="true"原因; 您可以给cash元素一些价值,但这将毫无意义。 现金支付的实例可能类似于清单7。

清单7.选择付款现金实例
<payment>
  <amount>10</amount>
  <cash xsi:isNil="true"/>
</payment>

您在这里只想说的是现金付款。 但是,在没有选择的情况下,没有办法表明这一点。

在清单2的CashPayment类型中,我随身携带了cash元素,因为我只是应用了转换规则,但实际上并不需要它。 您所需要的只是表明这是一种现金类型,仅此而已,并且由于多态性而已。 因此CashPayment选项将扩展Payment类型,但不添加任何新内容。 清单8显示了CashPayment类型的改进版本。 清单9显示了这种类型的实例。

清单8.改进的多态CashPayment
<complexType name="CashPayment">
  <complexContent>
    <extension base="tns:Payment">
      <sequence/>
    </extension>
  </complexContent>
</complexType>
清单9.多态支付现金实例
<payment xsi:type="CashPayment">
  <amount>10</amount>
</payment>

摘要

在某些情况下, xsd:choice类型不是要使用的最佳类型。 例如,当使用JAX-RPC映射规则将choice类型映射到Java语言时,最终会得到Java映射,这不是非常用户友好的。 如果可以控制架构,则可能需要将包含xsd:choice的类型转换为一组多态类型。 您不仅会得到一个更加用户友好的映射,而且多态性比xsd:choice更健壮。


翻译自: https://www.ibm.com/developerworks/xml/library/ws-tip-xsdchoice/index.html

xsd 两个xsd整合

 类似资料: