2

我需要验证 BizTalk 架构中元素的日期范围。我收到了开始日期在结束日期之前的日期(20130521-20130501)。我知道我可以在映射中使用 XSLT 和 C# 轻松解析和验证此字符串,但是,我需要将验证作为架构的一部分,以便如果收到具有此格式日期的事务,BizTalk 将拒绝 EDI 事务并将 999 拒绝返回给发件人。

我已经阅读了许多建议不要对日期范围使用正则表达式验证的帖子,但除了创建自定义管道组件或使用 C# 之外,我看不到任何其他方式。有一个模式属性允许使用正则表达式来验证输入数据。

我对正则表达式一点也不擅长,需要一些帮助来弄清楚如何验证开始日期是否小于或等于结束日期。日期作为字符串接收。我已经阅读了有关在“-”上拆分字符串的信息,但不知道如何比较结果。任何帮助,将不胜感激。

4

2 回答 2

7

免责声明:我使用的是 PHP,这意味着我使用的是 PCRE 正则表达式风格。

问题

似乎您没有意识到正则表达式的局限性,但这没关系。
真正的问题是以下解决方案:检查是否x =< y匹配。

极限

为什么 ?好吧,您要检查是否start date =< end date. 正则表达式的思想是按照某种正则模式匹配某些字符。单独的正则表达式无法检查是否x < y因为正则表达式没有逻辑运算符> <

绕过一定的限制

正则表达式可以做的是检查是否x = y. 例如说我有以下字符串,我想获取所有行x = y

10 = 10
15 = 51
33 = 31
100 = 101
780 = 780

我们可以使用以下正则表达式:^(\d+)\s*=\s*\1$m修饰符。这是什么意思 ?

  • ^: 行首
  • (\d+):分组并匹配任何数字一次或多次
  • \s*=\s*: 匹配空白 0 次或多次,然后匹配=任何空白 0 次或多次
  • \1: 指的是第 1 组,所以只有当它与第 1 组中匹配的内容相同时才匹配。
  • $: 行结束
  • m修饰符:多行。分别制作^$匹配行的开始和结束
    在线演示

概念证明

让我们进一步破解。对于这个POC,我们将匹配以下内容:x-ywhere0 =< x =< 9和。我们能做的是尝试匹配所有可能的位置。所以如果那么,如果那么,如果那么等等。由于正则表达式有语句,我们可以编写以下正则表达式:Online demo 你看到了吗?一个简单的比较实际上太长了!这就是为什么任何理智的人都会使用内置语言工具对其进行解析和验证的原因。0 =< y =< 9x =< y
x =< yx=0y=[0-9]x=1y=[1-9]x=2y=[2-9]or
0-[0-9]|1-[1-9]|2-[2-9]|3-[3-9]|4-[4-9]|5-[5-9]|6-[6-9]|7-[7-9]|8-[8-9]|9-9

打破正则表达式的法则

我们将使用 PHP 生成一个正则表达式:

$start = strtotime('2013-01-01'); // Start date
$end = strtotime('2013-03-01'); // End date
$range = array_map(function($v){return date('Ymd', $v);}, range($start, $end, 86400)); // Creating the range of dates
$result = ''; // Declaring an empty variable to store our regex in it

for($i=$start;$i<=$end;$i+=86400){ // loop each day
    $result .= '(?:' . date('Ymd', $i) . '-(?:'. implode('|', $range) . '))|'; // building our regex
    array_shift($range); // removing first element of range
}
$result = substr($result, 0, -1); // removing last | since we don't need it
echo $result; // Output

上面的代码将生成一个正则表达式,2013-01-012013-03-01可以x =< yx-y. 此正则表达式优化,约为17KB。那么想象一下,如果我将它配置为验证 10 年的范围,这个正则表达式的大小?请注意,大小呈指数增长。我尝试了 4 个月的间隔,但我收到一个错误/警告,说表达式太长。
由于正则表达式太长,我无法对其进行在线演示,但这是 PHP 中的代码:

$string = '20130101-20130101
20130201-20130101
20130105-20130120
20130201-20130301
20130210-20130215
20130301-20130301
20130301-20130201
'; // A sample

$regex = file_get_contents('regex.txt'); // Get the regex from a file (which we generated previously)
preg_match_all('#'.$regex.'#', $string, $matches); // Let's regex !
print_r($matches[0]); // Printing the matches ...

输出:

Array
(
    [0] => 20130101-20130101
    [1] => 20130105-20130120
    [2] => 20130201-20130301
    [3] => 20130210-20130215
    [4] => 20130301-20130301
)

正则表达式的在线转储   |   在线 PHP 演示

结论

请不要考虑使用正则表达式来完成此任务,否则您将遇到 10 个问题 :)

于 2013-06-09T15:08:53.237 回答
0

您可以将BizTalk 业务规则引擎管道框架与 BRE 策略结合使用来验证日期范围,而不是编写自己的自定义组件来进行验证。

完全披露:这个框架是由我的一位同事编写的。

于 2015-02-23T21:49:53.133 回答