【问题标题】:XSD regex for "four alphanumerics, but not all digits"?用于“四个字母数字,但不是所有数字”的 XSD 正则表达式?
【发布时间】:2024-01-20 03:54:01
【问题描述】:

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

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

这是我遇到困难的后一部分,“至少一个”或“但不是”。

我已经想过和/或尝试过:

字符类减法(但我认为这里没有办法定义“类”?)

<!-- 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 正则表达式可能不是最好的方法?

【问题讨论】:

标签: regex xml xsd logic alphanumeric


【解决方案1】:

XML Schema regex 不支持lookarounds,所以你只能拼出正则表达式:

<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 [...](字符类)中。

【讨论】:

  • 不过,还有更多可能的组合。我认为它类似于 2 * 4!不是吗?
  • 您需要确保在 4 个字符的字母数字字符串中至少有 1 个 alpha 字符,对吗?所以,上面的表达式应该有效。请在线尝试,让我知道您在现实生活中的期望。
  • 现在我再看一遍,我知道它是如何工作的;反过来,这 4 个位置中的每一个都仅限于 alpha。是的,这在逻辑上与“至少有一个 alpha。NICE 的想法!
【解决方案2】:

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


XSD 1.0

与 Wiktor Stribiżew 的 good idea (+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>

【讨论】:

  • 你的意思是(在 XSD 中,多个模式代表替代品。)
  • 见第二感alternation
  • 感谢@kjhuges - 包容性析取胜利!
【解决方案3】:

鉴于长度是固定的,另一个简单的解决方案是结合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>

【讨论】:

  • 爱它!这是值得被接受的答案。
最近更新 更多