Nasıl düzenli ifadeler kullanarak kapalı değil son HTML etiketini bulmak için?

4 Cevap php

Ben bu dizesi vardır Diyelim

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

Bu son kapanmamış etiketi çünkü sonuç "h1" olmak istiyorum

Başka bir örnek,

ise string

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

Bu son kapanmamış etiketi çünkü sonuç: "img" etiketi olmalıdır

Ben düzenli ifadeler tarafından yapılabilir biliyordum ama ben normal ifadeler kullanarak iyi değilim

4 Cevap

Ben bunu arıyor bir model değil çünkü, sadece birkaç düzenli ifadeler ile bunu yapmak mümkün olduğunu sanmıyorum.

Ben bir yığın kullanarak dize yoluyla gitmek istiyorum ve her size yığına koymak bir açılış etiketi görmek ve her şey sen eşleştirmesi yığından kaldırmak etiketi kapanış bulabilirsiniz.

Yani example1 ilk parçası geçti ise:

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

Sizin yığını olmalıdır:

html,body,h1,b

Sonraki b kapanır ve yığından çıkarın, böylece yığını gibi görünür:

html, body, h1

Şimdi (h1) ve yığının üstüne bulunuyor etiketi her zaman aradığınız biridir.

Ben ne demek istediğimi olsun umut, değilse bana bildirin.

Benim tavsiyem bir gerçek ayrıştırıcı değil, bir regex kullanmaktır.

Neredeyse normal bir ifade yazmak için başladı, ama ben de potansiyel bir kapanış etiketi olarak değerlendirilebilir olabilir metin içeren yorumlar ve (örneğin öznitelik değerleri gibi) dizeleri görmezden olduklarını anlamışlardır sonra vazgeçti:

 $string = "<html>
                 <body>
                 <h1>
                 <b>aaa</b> bbbb
                 <!--</h1> maybe it's silly to have such a comment but who knows-->
                 ";

Aşağıdaki kod ayrıştırma yapmak için regexes bir çift kullanır. Rasgele boşluk eklerken o gerçek dünya html kolayca kırılabilir ama dikkat edin, sekmeler içerisinde, etiket ve kod Etz. Aşağıdaki kod ile sorun kodu çalıştırmak için test durumlarda bir dizi içerir.

Burada fikri ilk kapanış etiketleri ile çıkarın, sonra, etiketleri html temizlemek ve nihayet mevcut son etiketi döndürmektir.

<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>