RegEx для соответствия вложенности схемы - PullRequest
2 голосов
/ 01 мая 2019

Мне нужно обнаружить вложение одного тега в другой, чтобы вызвать ошибку.

Примеры:

anything <amb id="1">word1</amb> anything <amb id="2">word2</amb> anything // OK

anything <amb id="1">anything<amb id="2">word2</amb>anything</amb> anything // KO

Поэтому необходимо обнаружить наличие тегов <amb... или </amb> между тегами <amb... и </amb>

У меня есть начало шаблона, но я не могу управлять вложенным присутствием тега.

// #\<amb(.*?)\<\/amb\># => OK : detect the first level
$pattern = '#\<amb(?!\<amb)\<\/amb\>#'; // KO

if(preg_match($pattern, $string)) {
  throw new Exception('No nested tags are allowed.');
}

Как мне решить эту проблему?

Ответы [ 2 ]

3 голосов
/ 01 мая 2019

Один из способов проверить вложение тегов - проверить, появляются ли два непрерывных тега <amb без тега </amb>, и вы можете отклонить строку, указав, что теги вложены. Регулярное выражение, основанное на этом негативном взгляде, должно делать свою работу,

^(?!.*<amb(?:(?!<\/amb).)+<amb).+$

Regex Demo 1

Аналогичным образом, другой способ - проверить, появляются ли два непрерывных тега <\/amb> без тега <amb, это означает, что теги вложены, и снова вы можете отклонить строку, используя это регулярное выражение на основе отрицательного взгляда,

^(?!.*<\/amb>(?:(?!<amb).)+<\/amb>).+$

Regex Demo 2

Дайте мне знать, если это работает для вас.

1 голос
/ 01 мая 2019

Для этого вам не нужны регулярные выражения. Это боль .Что вы можете сделать, это взорвать строку на </amd> и затем проверить, что каждая часть содержит не более одного <amb.Вот так:

function correctlyNested($html, $tag)
{
    foreach (explode("</$tag>", strtolower($html)) as $part) {
       if (substr_count($part, "<$tag") > 1) return false; // it is KO
    }
    return true; // it is OK
}


$tests = ['anything <amb id="1">word1</amb> anything <amb id="2">word2</amb> anything',
          'anything <amb id="1">anything<amb id="2">word2</amb>anything</amb> anything'];

foreach ($tests as $test) {
    echo $test . (correctlyNested($test, "amb") ? " // OK<br>" : " // KO<br>");
}

Этот код легко понять и поддерживать.Я добавил strtolower(), чтобы показать, насколько просто расширить этот код.

...