好的,OP 说服了我,虽然提到的另一个问题 https://stackoverflow.com/questions/9889206/xsd-restriction-that-negates-a-matching-string有一个重叠的主题,事实上,禁止字符串在所有位置都被禁止,而不仅仅是作为前缀,这使得事情变得复杂到需要单独的答案,至少对于 XSD 1.0 的情况是这样。 (我开始将此答案添加为我对另一个问题的答案的附录,并且它变得太大了。)
这里可以使用两种方法。
First, 在 XSD 1.1 中,形式的简单断言
not(matches($v, 'FILENAME'))
应该做这项工作。
第二,如果一个人被迫与一个人一起工作XSD 1.0处理器,需要一种模式来匹配所有且仅不包含禁止子字符串(此处为“FILENAME”)的字符串。
实现此目的的一种方法是确保字符“F”永远不会出现在输入中。这太激烈了,但它确实完成了这项工作:不包含禁止字符串第一个字符的字符串不包含禁止字符串。
但是包含“F”的字符串又如何呢?只要字符串“ILENAME”后面没有“F”,它们就可以。
更抽象地讲最后一点,我们可以说任何可接受的字符串(任何不包含字符串“FILENAME”的字符串)都可以分为两部分:
- 不包含字符“F”的前缀
- 出现零次或多次“F”,后跟与“ILENAME”不匹配且不包含任何“F”的字符串。
前缀很容易匹配:[^F]*
.
以 F 开头但不匹配 'FILENAME' 的字符串稍微复杂一些;正如我们不想禁止所有出现的“F”一样,我们也不想禁止“FI”、“FIL”等——但是每次出现这样的危险字符串后都必须跟随字符串的末尾,或者与禁止字符串的下一个字母不匹配的字母,或者另一个开始我们需要测试的另一个区域的“F”。因此,对于禁止字符串的每个正确前缀,我们创建一个以下形式的正则表达式
$prefix || '([^F' || next-character-in-forbidden-string || ']'
|| '[^F]*'
然后我们用 or-bar 连接所有这些正则表达式。
在这种情况下,最终结果如下所示(我在这里和那里插入了换行符,以使其更易于阅读;在使用之前,需要将它们撤回):
[^F]*
((F([^FI][^F]*)?)
|(FI([^FL][^F]*)?)
|(FIL([^FE][^F]*)?)
|(FILE([^FN][^F]*)?)
|(FILEN([^FA][^F]*)?)
|(FILENA([^FM][^F]*)?)
|(FILENAM([^FE][^F]*)?))*
需要牢记两点:
- XSD 正则表达式是隐式锚定的;使用非锚定正则表达式评估器对此进行测试将不会产生正确的结果。
- 起初可能并不明显为什么选择中的替代方案都以
[^F]*
代替.*
。考虑字符串“FEEFI FILENAME”可能会有所帮助。我们必须检查every出现“F”以确保其后面没有“ILENAME”。