XSD 中的枚举值哪种方法更好?模式验证还是业务验证?

Which approach is better for enum values in an XSD? Schema validation or business validation?

例如,我可以定义一个枚举,所以收到的 XML 会尽快得到验证,但是如果枚举发生变化,我将不得不公开一个新版本的 Web 服务。

<xsd:simpleType name="MyType">
    <xsd:restriction base="xsd:token">
        <xsd:enumeration value="VALUE_ONE"/> 
        <xsd:enumeration value="VALUE_TWO"/> 
        <xsd:enumeration value="VALUE_THREE"/>
    </xsd:restriction>
</xsd:simpleType>

<xsd:complexType name="Person">
    <xsd:sequence>
        <xsd:element name="myType" type="MyType"/> 
        <xsd:element name="name" type="xs:string"/>
    </xsd:sequence>
</xsd:complexType>

另一方面,我可以简单地使用字符串类型,并在后端验证值,返回业务错误:

<xsd:complexType name="Person">
    <xsd:sequence>
        <xsd:element name="myType" type="xs:token"/> 
        <xsd:element name="name" type="xs:string"/>
    </xsd:sequence>
</xsd:complexType>

然后,如果在某个时候我的后端枚举器发生变化,我应该只更改业务验证,或者什么都不做,如果验证只是检查该值是否与我的后端枚举的值之一相对应。

正如我在上面的评论中提到的,这是一个关于 trade-offs 的问题。你必须问问自己,如果你这样做,你会得到什么,会失去什么。

如果您之后不需要更改接受值列表,那么在 XSD 中定义枚举效果很好。如果您需要对其进行更改,那么您可以打破与客户的合同,强制他们从 WSDL 重建他们的代理客户端,或者强制他们实现您的服务的不同版本以使用新值。为如此小的更改进行 Web 服务版本控制将是矫枉过正(对于客户端、维护等)。

字符串类型更灵活。技术契约是一样的,不需要重建和重新编译从 WSDL 生成的代理客户端,它也消除了对契约进行版本控制的需要。我个人会选择这个选项。

我有时使用的第三种选择是提供额外的 Web 服务操作或增强其他操作对 return“元信息”的响应。所以基本上:

  • 您向您的服务添加另一个操作,例如 <getAvailableTitles>,其中 return 是可用标题的列表(合同保持不变;它也比免费输入字符串更安全),或者,
  • 当客户端调用另一个操作时,例如,我不知道 <getPersonDetails> 你 return 有关此人的详细信息,并使用 [=29] 的元信息增强结果=] 编辑人员详细信息时可以使用的头衔列表。

第二种方法最适合事物经常变化的情况,而第一种方法最适合事物很少变化的情况(调用的结果甚至可以缓存一段时间,因此客户端不需要调用它每次他们需要使用标题时)。