可以使用多种可能的复杂类型重载XSD元素吗?

Edw*_*lin 7 xml xsd

我有一个模式定义了一个事件记录,用于在发布/订阅方案中的两个系统之间传递消息.该事件包括"payload"元素event_data,其中包含消息的详细信息.复杂的是,有效载荷可以是30多种类型中的任何一种,每种类型都在其自己的XSD中定义.

例如(剥离):

<event>
   <event_name>new_phone_number</event_name>
   <event_data>
      <areacode>303</areacode>
      <number>555-1212</number>
      <extension>31</extension>
   </event_data>
</event>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,event_data的类型为phone_number,它在导入的XSD中的其他位置定义.但我想要做的是使用相同的机制来携带其他类型的结构化消息数据.例如,也许这是一个工作变更事件,定义为类型job_details:

<event>
   <event_name>new_job</event_name>
   <event_data>
      <job_title>CEO</job_title>
      <start_date>01/01/2012</start_date>
      <location>Main Office</location>
   </event_data>
</event>
Run Code Online (Sandbox Code Playgroud)

存储在event_data元素中的内部记录的类型为job_details,如导入的XSD中所定义.类型事件的"外部"记录只不过是一种携带"内部"记录中包含的有效负载的方法.

到目前为止,我已经研究了三种攻击方法,每种方法都有问题:

  1. 使用"选择"构造列出所有可能的记录类型.问题似乎是,选择列表中的所有条目共享相同的元素名称不是自然的xml/xsd.

  2. 我想这不是试图在event_data元素中包含一个结构化的子记录,而是可以简单地有一个反映每个可能的子记录类型的可选属性.每次将有一个独特的名字,当然,这样你就会有一个属性NEW_PHONE_NUMBER,一个用于new_job,依此类推.除了潜在的可维护性和丑陋问题之外,我不确定如何强制执行该操作,并且在给定的事件实例中只传递一个属性.我可以忍受这一点,但它使代码变得脆弱.

  3. 有人通过建议使用联合回答了类似的问题 - 但这似乎只适用于简单类型.不会涵盖我的用例.

难倒!任何指导?

xcu*_*cut 1

您可以通过xsi:type在实例文档中使用覆盖来完成此操作。XML 处理器无法“推断”类型,您需要提供这一点。例子:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <event>
     <event_name>new_phone_number</event_name>
     <event_data xsi:type="PhoneNumberData">
        <areacode>303</areacode>
        <number>555-1212</number>
        <extension>31</extension>
     </event_data>
  </event>
</root>
Run Code Online (Sandbox Code Playgroud)

请注意,您必须定义一个基本复杂类型EventData,并且PhoneNumberData必须从中派生,才能正常工作。