【问题标题】:can an XSD element be overloaded with multiple possible complex types?一个 XSD 元素可以用多种可能的复杂类型重载吗?
【发布时间】:2011-09-30 01:29:04
【问题描述】:

我有一个模式,它定义了一个 事件 记录,用于在发布/订阅方案中的两个系统之间传递消息。该事件包括一个“有效负载”元素 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>

在这种情况下,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>

存储在 event_data 元素中的内部记录属于 job_details 类型,在导入的 XSD 中定义。 event 类型的“外部”记录只不过是承载“内部”记录中包含的有效负载的一种方式。

到目前为止,我已经研究了三种方法来解决这个问题,每种方法都有问题:

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

  2. 我想与其尝试在 event_data 元素中包含结构化子记录,我可以简单地使用一个可选属性来反映每种可能的子记录类型。当然,每个都有一个唯一的名称,因此您将有一个 new_phone_number 的属性,一个 new_job 的属性,依此类推。除了这里潜在的可维护性和丑陋问题外,我不确定如何强制在给定的事件实例中传递一个且只有一个属性。我可以忍受,但这会使代码变得脆弱。

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

难倒!有什么指导吗?

【问题讨论】:

    标签: xml xsd


    【解决方案1】:

    您也可以考虑使用substitution groups,尽管它可能不像之前建议的两个那样适合您的问题。替换组更像是“使用特定元素而不是通用元素”,而您的问题似乎更像是“使用特定类型而不是通用类型”。

    【讨论】:

      【解决方案2】:

      在 XSD 1.1(在 Xerces 和 Saxon 中实现)中,您可以使用称为“条件类型分配”的功能来执行此操作,由此在元素声明级别,您可以从通过应用选择的替代列表中决定使用哪种类型元素属性的 XPath 表达式。

      【讨论】:

      • 谢谢。您是否知道 BizTalk 是否支持 xsd 1.1?我一直在浏览 BizTalk 的东西,但没有找到它……那是我的目标平台,带有 Ruby pub-sub 客户端。
      • XSD 1.1 是非常新的版本,实际上它甚至还没有完成,而且微软并没有以匆忙实施新标准而闻名。
      【解决方案3】:

      您可以通过在您的实例文档中使用 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>
      

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

      【讨论】:

      • 这很有趣 - 谢谢!因此,由于我的类型非常多样化,几乎没有共同的元素,所以基本类型会非常薄,对吧?我会通过使用 xs:extension 块扩展特定类型来派生?
      猜你喜欢
      • 2020-01-27
      • 1970-01-01
      • 2023-03-04
      • 2015-07-11
      • 1970-01-01
      • 2016-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多