首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何正确地转义XSD模式中的正则表达式模式?

如何正确地转义XSD模式中的正则表达式模式?
EN

Stack Overflow用户
提问于 2016-04-26 09:21:41
回答 2查看 2.3K关注 0票数 0

我需要满足一个只接受MM/DD/YYYY形式的值的要求。

从我所读到的:https://www.w3.org/TR/xmlschema11-2/#nt-dateRep使用

代码语言:javascript
运行
复制
<xs:simpleType name="DATE">
        <xs:restriction base="xs:date"/>
    </xs:simpleType>

因为它的regex显然不支持这种格式,所以无法工作。

我发现并调整了这种格式:

代码语言:javascript
运行
复制
^(?:(?:(?:0?[13578]|1[02])(\/)31)\1|(?:(?:0?[1,3-9]|1[0-2])(\/)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:0?2(\/)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\/)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

以下表格:

代码语言:javascript
运行
复制
\^\(\?:\(\?:\(\?:0\?\[13578\]\|1\[02\]\)\(\\/\)31\)\1\|\(\?:\(\?:0\?\[1,3-9\]\|1\[0-2\]\)\(\\/\)\(\?:29\|30\)\2\)\)\(\?:\(\?:1\[6-9\]\|\[2-9\]\d\)\?\d{2}\)$\|\^\(\?:0\?2\(\\/\)29\3\(\?:\(\?:\(\?:1\[6-9\]\|\[2-9\]\d\)\?\(\?:0\[48\]\|\[2468\]\[048\]\|\[13579\]\[26\]\)\|\(\?:\(\?:16\|\[2468\]\[048\]\|\[3579\]\[26\]\)00\)\)\)\)$\|\^\(\?:\(\?:0\?\[1-9\]\)\|\(\?:1\[0-2\]\)\)\(\\/\)\(\?:0\?\[1-9\]\|1\d\|2\[0-8\]\)\4\(\?:\(\?:1\[6-9\]\|\[2-9\]\d\)\?\d{2}\)$

现在,我不再获得XML编辑器中的无效转义错误(使用XML ),但我得到了以下一个:

代码语言:javascript
运行
复制
invalid-escape: The given character escape is not recognized.

我在这里按照XML规范进行了转义:https://www.w3.org/TR/xmlschema-2/#regexs第F.1.1节有一个转义表。

有人能帮我把这个钉下来吗?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-26 10:53:12

如果您检查XSD语法资源,您将注意到不支持非捕获群 ((?:...)),也不支持反向引用 (用于引用捕获组( (...))捕获的文本的类似\n的实体)。

因为惟一的分隔符是/,所以可以完全消除反向引用。

使用

代码语言:javascript
运行
复制
((((0?[13578]|1[02])/31)/|((0?[13-9]|1[0-2])/(29|30)/))((1[6-9]|[2-9]\d)?\d{2}‌​)|(0?2/29/(((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[35‌​79][26])00))))|(0?[1-9]|1[0-2])/(0?[1-9]|1\d|2[0-8])/(1[6-9]|[2-9]\d)?\d{2})

请参阅这个regex演示

注意这一点。转到regular-expressions.info

特别值得注意的是,完全没有锚点,如插入符和美元、单词边界和查找。XML模式总是隐式地锚定整个正则表达式。正则表达式必须匹配整个元素才能被认为是有效的。

因此,在XSD regex.中,不应该使用^ (string的开始)和 $ (string的结束)。

/符号在regex类型中是regex分隔符,而在XSD中,没有regex分隔符(因为惟一的操作是匹配的,并且没有修饰符:http://www.regular-expressions.info/xml.html)。因此,不会在XSD regex中逃避。

在线测试人员注意到

如果您在regex101.com或类似站点上进行测试,请注意,在大多数情况下,如果选择/作为正则分隔符,则需要转义它。您可以在完成测试后在\之前安全地删除/

票数 1
EN

Stack Overflow用户

发布于 2016-04-26 10:52:33

好的,从这里开始(为了便于阅读,我将插入换行符):

代码语言:javascript
运行
复制
    ^(?:(?:(?:0?[13578]|1[02])(\/)31)\1|(?:(?:0?[1,3-9]|1[0-2])(\/)
(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$
|^(?:0?2(\/)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|
^(?:(?:0?[1-9])|(?:1[0-2]))(\/)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

可怕的东西。现在在XSD中:

(a)没有^$锚点,不需要它们(模式是隐式锚定的)。那就把他们干掉。您的反应是以\^\$的形式将它们转义,但这是没有意义的:您实际上不希望在输入中出现拐弯抹角和美元符号。

(b) XSD不识别非捕获组(?:xxxx)。只需用捕获组替换它们--也就是说,再次删除?:,您已经摆脱了问号,这根本没有任何意义。

(c) \d可能应该是[0-9],除非您实际上想要匹配非ASCII数字(例如泰国或东方阿拉伯数字)。

(d) Slash (/)不需要转义,也确实不能转义。所以将\/替换为/

(e)我看到了一些背景资料,\1\2\4。XSD正则表达式不允许反向引用。但据我所见,这个正则表达式中的反向引用没有任何用处。它们中的大多数似乎是对表单(\/)中只能匹配单个斜杠的一组的回引用,因此可以简单地将反向引用\1替换为/。也许它们是某种早期正则表达式的回行,允许选择分隔符,但要求它们是一致的。

从您解决这里的问题的尝试来看,在我看来,您对正则表达式还没有非常透彻的理解。我担心要做到这一点,您将不得不咬紧牙关,学习它是如何工作的;调试复杂的正则表达式是很困难的,而且您将无法通过尝试和错误得到正确的结果。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36860613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档