XSD "four alphanumerics, but not all digits" 的正则表达式?

XSD regex for "four alphanumerics, but not all digits"?

我正在尝试为必须包含四个字母数字(仅限大写)但不能包含全数字组合的元素编写 XML 架构数据类型。

换句话说,A-Z 或 0-9 中的四个序列,至少包含 A-Z 中的一个。

这是我遇到困难的后半部分,"at least one" 或 "but not"。

我想过 and/or 试过:

字符class减法(不过我觉得这里没办法定义"classes"?)

<!-- no example -->

合并 2 xs:restrictions

<xs:restriction>
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:pattern value="[0-9A-Z]{4}"/>
        </xs:restriction>
      </xs:simpleType>
      <xs:pattern value="[^(\d\d\d\d)]"/>
    </xs:restriction>

在两种数据类型中组合 2 xs:patterns

  <xs:simpleType name="4alpha-at-least-one-letter">
    <xs:restriction base="my-namespace:FourAlphanumericsType">
      <xs:pattern value="[^(\d\d\d\d)]"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="FourAlphanumericsType">
    <xs:restriction base="xs:string">
      <xs:pattern value="[0-9A-Z]{4}"/>
    </xs:restriction>
  </xs:simpleType>

我想这些都是死胡同,我要么在正则表达式世界中遗漏了一些东西,要么 XML 正则表达式可能不是执行此操作的最佳方法?

XML Schema regex不支持lookarounds,所以只能拼出regex:

<xs:pattern value="[A-Z][A-Z0-9]{3}|[A-Z0-9][A-Z][A-Z0-9]{2}|[A-Z0-9]{2}[A-Z][A-Z0-9]|[A-Z0-9]{3}[A-Z]"/>

参见regex demo

如果您还需要匹配小写字母,请将a-z添加到ech [...](字符class)中。

更新:不要错过。我会在这里留下我的答案,以了解它可能有的任何有用的花絮,但 sergioFC 是总体上最好的解决方案。


XSD 1.0

通过使用多个模式,可以比 Wiktor Stribiżew 的 (+1) 略微提高可读性:

<xs:simpleType name="AtLeastOneLetterInFourAlphaType">
   <xs:restriction base="xs:string">
     <xs:pattern value="[A-Z][A-Z0-9]{3}"/>
     <xs:pattern value="[A-Z0-9][A-Z][A-Z0-9]{2}"/>
     <xs:pattern value="[A-Z0-9]{2}[A-Z][A-Z0-9]"/>
     <xs:pattern value="[A-Z0-9]{3}[A-Z]"/>
   </xs:restriction>
</xs:simpleType>

(在XSD中,多个模式代表交替。)

XSD 1.1

XSD 1.1 的断言设施可以表达值不能是数字的约束,这有效地要求伙伴模式中表达的至少一个字符是非数字的:

<xs:simpleType name="AtLeastOneLetterInFourAlphaType">
  <xs:restriction base="xs:string">
    <xs:pattern value="[A-Z0-9]{4}"/>
    <xs:assertion test="not($value castable as xs:integer)"/>
  </xs:restriction>
</xs:simpleType>

鉴于长度是固定的,另一种简单的解决方案是结合xs:patternxs:length限制:

<xs:simpleType name="x">
   <xs:restriction base="xs:string">
     <xs:pattern value="[A-Z0-9]*[A-Z][A-Z0-9]*"/>
     <xs:length value="4"/>
   </xs:restriction>
</xs:simpleType>