Выберите первый тег абзаца, не содержащийся в другом теге, используя RegEx (в стиле Perl) - PullRequest
0 голосов
/ 14 декабря 2011

У меня есть этот блок html:

<div>
  <p>First, nested paragraph</p>
</div>
<p>First, non-nested paragraph.</p>
<p>Second paragraph.</p>
<p>Last paragraph.</p>

Я пытаюсь выбрать первый, не вложенный абзац в этом блоке.Я использую PHP (стиль Perl) preg_match, чтобы найти его, но не могу понять, как игнорировать тег p, содержащийся в div.

Это то, что у меня есть, но он выбираетсодержание первого абзаца, содержащегося выше.

/<p>(.+?)<\/p>/is

Спасибо!

РЕДАКТИРОВАТЬ

К сожалению, я не могу позволить себе такую ​​роскошьDOM Parser.

Я полностью благодарен за предложения не использовать RegEx для разбора HTML, но это не очень помогает моему конкретному случаю использования.У меня очень контролируемый случай, когда внутреннее приложение генерирует структурированный текст.Я пытаюсь заменить текст, если он соответствует определенному шаблону.Это упрощенный случай, когда я пытаюсь игнорировать текст, вложенный в другой текст, а HTML был простейшим примером, который я мог бы объяснить.Мой фактический случай выглядит примерно так (но гораздо больше данных и минимизировано):

#[BILLINGCODE|12345|11|15|2001|15|26|50]#
[ITEM1|{{Escaped Description}}|1|1|4031|NONE|15]
#[{{Additional Details }}]#
[ITEM2|{{Escaped Description}}|3|1|7331|NONE|15]
[ITEM3|{{Escaped Description}}|1|1|9431|NONE|15]
[ITEM4|{{Escaped Description}}|1|1|5131|NONE|15]

Мне нужно переформатировать определенный столбец определенных строк в тонну строк, похожих на эту.Помочь моему первому вопросу поможет настоящий проект.

Ответы [ 5 ]

2 голосов
/ 14 декабря 2011

Как насчет чего-то подобного?

<p>([^<>]+)<\/p>(?=(<[^\/]|$))

Делает ли предварительный просмотр, чтобы убедиться, что он не находится внутри закрывающего тега;но может быть в конце строки.Вероятно, есть лучший способ найти то, что находится в тегах абзаца, но вам следует избегать слишком жадного обращения (a. +? Будет недостаточно).

2 голосов
/ 14 декабря 2011

Ваше регулярное выражение не будет работать.Даже если у вас был только не вложенный абзац, ваши захватывающие скобки будут соответствовать First, non-nested ... Last paragraph..

Попробуйте:

<([^>]+)>([^<]*<(?!/?\1)[^<]*)*<\1>

и захватите \2, если \1is p.

Но анализатор HTML лучше справился бы с этим imho.

1 голос
/ 14 декабря 2011

«Вы не должны использовать регулярные выражения для разбора HTML.»

Это то, что все говорят, но на самом деле никто не предлагает пример того, как на самом деле это сделать, они просто проповедуют это. Что ж, благодаря некоторой мотивации из Леви Моррисон Я решил прочитать в DomDocument и выяснить, как это сделать.

Всем, кто говорит: «О, слишком сложно выучить парсер, я просто использую регулярное выражение». Ну, Я никогда ничего не делал с DomDocument или XPath раньше, и это заняло у меня 10 минут. Иди, прочитай документы по DomDocument и проанализируй HTML так, как ты должен.

$myHtml = <<<MARKUP
   <html>
       <head>
            <title>something</title></head>
       <body>
            <div>
                <p>not valid</p>
            </div>
            <p>is valid</p>
            <p>is not valid</p>
            <p>is not valid either</p>
            <div>
                <p>definitely not valid</p>
            </div>
       </body>
   </html>
MARKUP;

$DomDocument = new DOMDocument();
$DomDocument->loadHTML($myHtml);
$DomXPath = new DOMXPath($DomDocument);
$nodeList = $DomXPath->query('body/p');
$yourNode = $DomDocument->saveHtml($nodeList->item(0));

var_dump($yourNode)

// output '<p>is valid</p>'
1 голос
/ 14 декабря 2011

Используйте двух трехступенчатый процесс. Во-первых, молитесь, чтобы все было хорошо сформировано. Во-вторых, Во-первых, удалите все вложенное.

s{<div>.*?</div>}{}g;         # HTML example
s/#.*?#//g;                   # 2nd example

Тогда получите свой результат. Все, что осталось, теперь не вложено.

$result = m{<p>(.*?)</p>};    # HTML example
$result = m{\[(.*?)\]};       # 2nd example

(это Perl. Не знаю, как это будет выглядеть в PHP).

0 голосов
/ 14 декабря 2011

Возможно, вы захотите взглянуть на этот пост о разборе HTML с помощью Regex.

Поскольку HTML не является обычным языком (как и регулярные выражения), вы не можете обрезать произвольные фрагменты HTML с помощью Regex. Используйте HTML-анализатор, он сделает работу значительно более гладкой, чем попытка собрать какое-то регулярное выражение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...