Соответствующая пара тегов с помощью корпуса
-
18-09-2019 - |
Вопрос
Я пытаюсь получить определенные теги с их контентом из документа XHTML, но это соответствует неправильным тегам.
В следующем контенте:
<cache_namespace name="content">
<content_block id="15">
some content here
<cache_namespace name="user">
<content_block id="welcome">
Welcome Apikot!
</content_block>
</cache_namespace>
</content_block>
</cache_namespace>
Тег конечного значения content_block для id = "Gellw" на самом деле сопоставлен как окончательный тег первого открывающегося тега content_block.
Покраснение, которую я использую:
/<content_block id="(.*)">([\w\W]*?)<\/content_block>/i
Какие -нибудь указатели относительно того, где я терплю неудачу?
Решение
... и ответ всегда одинаковый: Html + regex не может быть сделана. Анкет Извиняюсь. Используйте библиотеку HTML -диаграммы для вашей конкретной структуры. Или, если ваш документ гарантированно содержит только действительный xhtml, примите подход XPath, предложенный Jitter в комментарии.
Другие советы
Это может помочь я нашел учебник на http://www.regular-expressions.info/examples.htmlкоторый упоминает о захвате пары строки, повторяющихся в данном тексте. Предложение - использовать? После.* Чтобы остановиться после первого появления конечной строки пары в тексте
Это известная проблема с Regex - вы не можете сопоставить пары. Сопоставление является либо жадным, в котором он соответствует последнему, который он находит, либо не-восточным, в котором он соответствует первой. Вы не можете убедить регулярность, чтобы считать открытие и закрытие кронштейнов.
Я бы порекомендовал загрузить его в DOM и использовать это. Если вы пытаетесь реализовать анализатор HTML, я бы порекомендовал использовать Regex для лексики, то тогдашний сияющий левый правый для анализа вывода вашего Lexer.
благодаря @Jan żankowski а также @ikegami, их ответ дал мне Inpiration
Позвольте мне использовать PHP, чтобы продемонстрировать код
<?php
$xml = <<<EOT
<cache_namespace name="content">
<content_block id="15">
some content here
<cache_namespace name="user">
<content_block id="welcome">
Welcome Apikot!
</content_block>
</cache_namespace>
</content_block>
</cache_namespace>
EOT;
preg_match('/<cache_namespace[^>]+>((?:(?!(<\/?div>)).)*)<\/cache_namespace>/s', $xml, $matches);
print_r($matches);
записка
s
Вариант: а.
В шаблоне совпадает со всеми персонажами, в том числе новичками- Ключ здесь в том, что
(?:(?!STRING).)*
к струнам как[^CHAR]*
для персонажей
результат
Array
(
[0] => <cache_namespace name="content">
<content_block id="15">
some content here
<cache_namespace name="user">
<content_block id="welcome">
Welcome Apikot!
</content_block>
</cache_namespace>
</content_block>
</cache_namespace>
[1] =>
<content_block id="15">
some content here
<cache_namespace name="user">
<content_block id="welcome">
Welcome Apikot!
</content_block>
</cache_namespace>
</content_block>
)
Расположение XHTML или XML не сложно. Я предположил, что у вас есть действительный или хорошо сформированный код.
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
my $xml = <<"EOF";
<cache_namespace name="content">
<content_block id="15">
some content here
<cache_namespace name="user">
<content_block id="welcome">
Welcome Apikot!
</content_block>
</cache_namespace>
</content_block>
</cache_namespace>
EOF
while ($xml =~ m!
<(content_block)\sid="welcome"> # Start tag definition.
(\s* # It may consists of
(?: <\!--.*?--> # - comment
| [^<]* # - text
| <[^>]+/> # - another closed tag
| <\s*(\w+)[^>]*> # - another tag with some content
(?2)+ # (recursive definition of possible tag content)
</\3>
)
)*
</\1>
!sxgc) {
print "==> $&\n\n";
}
Пожалуйста, измените определение TAG START для другого контента (например, <\s*(\w+)[^>]*+>
) В любом случае, это хорошая начальная точка.
Если вы не будете использовать рекурсию (строить с (?2)+
) ты застрянешь Такие примеры. Анкет Этот код может справиться с ними все (пожалуйста, посмотрите здесь раньше) или может легко адаптироваться к новым ситуациям.