Как найти последний HTML-тег, который не закрылся с помощью регулярных выражений? - PullRequest
1 голос
/ 05 августа 2009

Допустим, у меня есть эта строка

      $string = "<html>
                 <body>
                 <h1>
                 <b>aaa</b> bbbb
                 ";

Я хочу, чтобы результат был "h1", потому что это последний незакрытый тег

другой пример

если строка

     $string = "<body>
                <img src='' alt=
               ";

результат должен быть тегом "img", потому что это последний незакрытый тег

Я знал, что это можно сделать с помощью регулярных выражений, но я не очень хорош в использовании регулярных выражений

Ответы [ 4 ]

3 голосов
/ 05 августа 2009

Мой совет - использовать реальный парсер, а не регулярное выражение.

3 голосов
/ 05 августа 2009

Я сомневаюсь, что это можно сделать с помощью нескольких регулярных выражений, поскольку вы ищете не шаблон.

Я бы прошел строку, используя стек, и каждый раз, когда вы видите открывающий тег, вы помещаете его в стек, и каждый раз, когда вы находите соответствующий закрывающий тег, вы удаляете его из стека.

Итак, если вы прошли первую часть примера 1:

<html>
  <body>
    <h1>
      <b>

Ваш стек должен быть:

HTML, тело, h1, б

Далее b закрывается, и вы удаляете его из стека, поэтому ваш стек выглядит так:

html, тело, h1

Теперь тег, который находится сверху вашего стека (h1), всегда тот, который вы ищете.

Надеюсь, вы понимаете, о чем я, если не дадите мне знать.

0 голосов
/ 09 августа 2009

Код ниже использует несколько регулярных выражений для анализа. Помните, что HTML-код реального мира может легко сломать его при вставке случайных пробелов, вкладок и т. Д. Внутри тегов и кода. Приведенный ниже код включает в себя массив тестовых случаев для выполнения кода проблемы.

Идея состоит в том, чтобы сначала очистить HTML, затем удалить теги с закрывающими тегами и, наконец, вернуть последний доступный тег.

<html>

<head><title>Last Open HTML Tag</title>

<body>

<h1>Last Open HTML Tag</h1>
<?php

$htmlstrings[] ="<html>
                 <body>
                 <h1>
                 <b>aaa</b> bbbb
                 ";

$htmlstrings[] ="<html>
                 <body>
                 <h3>test</h3>
                 <h1>
                 <b>aaa <i>test2</i></b> <i>test</i> bbbb
                 ";

$htmlstrings[] = "<body>
                <img src='' alt=
               ";

$htmlstrings[] = "<body>
                < img src='' alt=
               ";

$num = 1;              
foreach( $htmlstrings as $rawstring){
    // First remove whitespace in tags
    $string = preg_replace ( "/<\s*(\w)/", "<$1", $rawstring);
//    $string = preg_replace ( "/<\s*/\s*(\w)/", "</$1", $string);

    $real_matches = array();

    // Find open html tag (<a ...)
    if( preg_match( "/<(\w*)\W[^><]*$/", $string, $matches) > 0){
        $real_matches = $matches;
    // Find html tag with no end tag (<h1>...)
    } else {
        $newstrin = null;
        while( true){
            $newstring = preg_replace( "/<(\\w*)>[^<>]*<\\/\\1>/s", "", $string);
            if( $newstring == $string){
                break;
            }
            $string = $newstring;
        }
        preg_match( "/<(\\w*)>[^<>]*$/", $newstring, $matches);
        $real_matches = $matches;
    }

    echo "<p>Parse $num\n";
    $rawstring = preg_replace ( "/</is", "&lt;", $rawstring);
    $rawstring = preg_replace ( "/>/is", "&gt;", $rawstring);
    echo "<br>$rawstring\n";
    foreach( $real_matches as $match){
        $result = preg_replace ( "/</is", "&lt;", $match);
        $result = preg_replace ( "/>/is", "&gt;", $result);
         echo "<br>" . $result . "\n";
    }
    $num++;

    echo "<br>LAST OPEN TAG: " . $matches[1] . "\n";
} 

?>
</body>
</html>
0 голосов
/ 05 августа 2009

Я почти начал писать регулярное выражение, но я сдался, поняв, что мне также нужно игнорировать комментарии и строки (например, значения атрибутов), содержащие текст, который потенциально может быть оценен как закрывающий тег:

 $string = "<html>
                 <body>
                 <h1>
                 <b>aaa</b> bbbb
                 <!--</h1> maybe it's silly to have such a comment but who knows-->
                 ";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...