Xsd 不允许特定字符串的XML架构限制模式

Xsd 不允许特定字符串的XML架构限制模式,xsd,pattern-matching,restriction,lookahead,Xsd,Pattern Matching,Restriction,Lookahead,我需要编写一个对字段有限制的XSD模式,以确保 该字段的值在任何位置都不包含子字符串文件名 例如,以下所有内容都必须无效: FILENAME ORIGINFILENAME FILENAMETEST 123FILENAME456 这些值都不应有效 在支持负前瞻的正则表达式语言中,我可以通过编写/^((?!FILENAME)。*$来实现这一点,但XSD模式语言不支持负前瞻 如何实现与/^((?!FILENAME)。*$具有相同效果的XSD模式限制 我需要使用模式,因为我无法访问XSD1.1断言,这

我需要编写一个对字段有限制的XSD模式,以确保 该字段的值在任何位置都不包含子字符串文件名

例如,以下所有内容都必须无效:

FILENAME
ORIGINFILENAME
FILENAMETEST
123FILENAME456
这些值都不应有效

在支持负前瞻的正则表达式语言中,我可以通过编写
/^((?!FILENAME)。*$
来实现这一点,但XSD模式语言不支持负前瞻

如何实现与
/^((?!FILENAME)。*$
具有相同效果的XSD模式限制

我需要使用模式,因为我无法访问XSD1.1断言,这是另一种明显的可能性


问题涉及类似的情况,但在这种情况下,禁止字符串仅作为前缀被禁止,这使得检查约束更容易。如何将解决方案扩展到包括我们必须检查输入字符串中的所有位置,而不仅仅是开始位置的情况?

好的,OP说服了我,虽然有一个重叠的主题,但事实上禁止的字符串在所有位置都被禁止,而不仅仅是作为前缀,使事情复杂到需要一个单独的答案,至少对于XSD1.0来说是这样。(我开始把这个答案作为我对另一个问题的答案的补充,它变得太大了。)

这里可以使用两种方法

首先,XSD1.1中的,一个简单的表单断言

not(matches($v, 'FILENAME'))
$prefix || '([^F' || next-character-in-forbidden-string || ']' 
    || '[^F]*'
我应该做这项工作

其次,如果一个人被迫使用xsd1.0处理器,那么他需要一个模式来匹配所有且仅匹配不包含禁止子字符串的字符串(此处为“FILENAME”)

一种方法是确保输入中永远不会出现字符“F”。这太激烈了,但它确实起到了作用:不包含禁止字符串的第一个字符的字符串不包含禁止字符串

但是包含“F”的字符串怎么办?只要没有“F”后跟字符串“ILENAME”,它们就可以了

将最后一点抽象化,我们可以说任何可接受的字符串(任何不包含字符串“FILENAME”的字符串)可以分为两部分:

  • 不包含字符“F”的前缀
  • 零次或多次出现“F”,后跟与“ILENAME”不匹配且不包含任何“F”的字符串 前缀很容易匹配:
    [^F]*

    以F开头但与“FILENAME”不匹配的字符串要复杂一些;正如我们不想取缔“F”的所有出现一样,我们也不想取缔“FI”、“FIL”等——但这种危险字符串的每一次出现都必须紧跟在该字符串的末尾,或者紧跟在与禁止字符串的下一个字母不匹配的字母后面,或者紧跟在另一个“F”后面,该“F”从我们需要测试的另一个区域开始。因此,对于禁止字符串的每个适当前缀,我们创建一个正则表达式

    not(matches($v, 'FILENAME'))
    
    $prefix || '([^F' || next-character-in-forbidden-string || ']' 
        || '[^F]*'
    
    然后我们用或条连接所有这些正则表达式

    本例的最终结果如下所示(我在这里和那里插入了换行符,以便于阅读;在使用之前,需要将它们取出来):

    要记住两点:

    • XSD正则表达式是隐式锚定的;使用非锚定正则表达式计算器进行测试将不会产生正确的结果
    • 一开始可能不太清楚为什么选择中的备选方案都以
      [^F]*
      而不是
      *
      结尾。考虑字符串“FEEFIFILENAME”可能会有所帮助。我们必须检查每一次出现的“F”,以确保后面没有“ILENAME”

    好的,OP说服了我,虽然有一个重叠的主题,但禁止字符串在所有位置都是禁止的,而不仅仅是作为前缀,这一事实使事情变得复杂,需要单独的答案,至少在XSD 1.0的情况下是如此。(我开始把这个答案作为我对另一个问题的答案的补充,它变得太大了。)

    这里可以使用两种方法

    首先,XSD1.1中的,一个简单的表单断言

    not(matches($v, 'FILENAME'))
    
    $prefix || '([^F' || next-character-in-forbidden-string || ']' 
        || '[^F]*'
    
    我应该做这项工作

    其次,如果一个人被迫使用xsd1.0处理器,那么他需要一个模式来匹配所有且仅匹配不包含禁止子字符串的字符串(此处为“FILENAME”)

    一种方法是确保输入中永远不会出现字符“F”。这太激烈了,但它确实起到了作用:不包含禁止字符串的第一个字符的字符串不包含禁止字符串

    但是包含“F”的字符串怎么办?只要没有“F”后跟字符串“ILENAME”,它们就可以了

    将最后一点抽象化,我们可以说任何可接受的字符串(任何不包含字符串“FILENAME”的字符串)可以分为两部分:

  • 不包含字符“F”的前缀
  • 零次或多次出现“F”,后跟与“ILENAME”不匹配且不包含任何“F”的字符串 前缀很容易匹配:
    [^F]*

    以F开头但与“FILENAME”不匹配的字符串要复杂一些;正如我们不想取缔“F”的所有出现一样,我们也不想取缔“FI”、“FIL”等——但这种危险字符串的每一次出现都必须紧跟在该字符串的末尾,或者紧跟在与禁止字符串的下一个字母不匹配的字母后面,或者紧跟在另一个“F”后面,该“F”从我们需要测试的另一个区域开始。因此,对于禁止字符串的每个适当前缀,我们创建一个正则表达式

    not(matches($v, 'FILENAME'))
    
    $prefix || '([^F' || next-character-in-forbidden-string || ']' 
        || '[^F]*'
    
    然后我们用或条连接所有这些正则表达式

    本例的最终结果类似于foll