检查字符串标题和内部编号列表级别

I need to correct a string with wrong heading-tags and missing p-tags:

<h3>1. Title</h3>
Text
<h3>1.1 Subtitle</h3>
Text
<h3>1.2. Subtitle</h3>

Should get

<h2>1. Title</h2>
<p>Text</p>
<h3>1.1. Subtitle</h3>
<p>Text</p>
<h3>1.2. Subtitle</h3>

That means every heading of a first level of the list should be a h2-tag. The second level could have the format 1.1. or 1.1, which should be corrected with the missing . If there is no tag at all, a p-tag should be added.

$lines = explode(PHP_EOL, $text);
foreach ($lines as $line) {
    if(!strpos($line,"<h")) $line = '<p>'.$line.'</p>';
    $output = $output.$line;
}

So this adds the missing p-tags, but I don't know how to take care of the heading tags and the optional missing point of the second level.

This will use a regular expression for getting the different parts, and determine what header level to use depending on the number (h2 for 1., h3 for 1.2 etc). This would work if the HTML you are parsing is really as simple as per your example. If not, I would strongly recommend that you take a look at the DOMDocument parser instead.

$html = <<<EOS
<h3>1. Title</h3>
Text
<h3>1.1 Subtitle</h3>
Text
<h3>1.2. Subtitle</h3>
Text
EOS;

$lines = explode(PHP_EOL, $html);

foreach ($lines as $line) {
    if (preg_match('/^<(\w.*?)>([\d\.]*)(.*?)</', $line, $matches)) {
        $tag    = $matches[1]; // "h3"
        $number = $matches[2]; // "1.2"
        $title  = $matches[3]; // "Subtitle"

        if ($tag == 'h3') {
            $level = preg_match_all('/\d+/', $number) + 1;
            $tag = 'h' . $level;
            if (substr($number, -1, 1) != '.')
                $number .= '.';

            $line = "<$tag>$number$title</$tag>";
        }
    }
    else {
        $line = "<p>$line</p>";
    }
    echo $line, PHP_EOL;
}

Output:

<h2>1. Title</h2>
<p>Text</p>
<h3>1.1. Subtitle</h3>
<p>Text</p>
<h3>1.2. Subtitle</h3>
<p>Text</p>

try with this :

 $lines = explode(PHP_EOL, $text);
 foreach ($lines as $line) {
    if(strpos($line,"<h") === false) $line = '<p>'.$line.'</p>';
    $output = $output.$line;
 }

or this

$lines = explode(PHP_EOL, $text);
foreach ($lines as $key => $line) 
{ 
   if($key%2!=0) $line = '<p>'.$line.'</p>';
   $output = $output.$line;

}

How about this?

$text = '<h3>1. Title</h3>
         Text 
         <h3>1.1 Subtitle</h3>
         Text
         <h3>1.2. Subtitle</h3>';
$lines = explode(PHP_EOL, $text);

$lines[0] = str_replace('h3','h2',$lines[0]); // Need to replace h3 to h2   only on First node
// replace a array of string
$search_str = array('.1 ', '.2 ');
$replace_str = array('.1. ', '.2. ');

foreach($lines as $line){
    if(!strchr($line,"<")){
       $line = '<p>'.$line.'</p>';
    }
$line = str_replace($search_str, $replace_str, $line);
print $line;
}