Is there a way to detect if string have valid HTML syntax in PHP or symfony?

Viewed 88

simply i have string like:

<h2 Article name</h2>This is an idea.<ul style="color:green;"><li>option 1</li><li>option 2</li><li>option 1<li></ul>

As you can see it is not valid, how can symfony or just PHP detect this and return where the error is?

I have found the following code:

private function validateHTML($string)
{
    preg_match_all('#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?>#iU', $string, $result);
    $openedTags = $result[1];
    preg_match_all('#</([a-z]+)>#iU', $string, $result);
    $closedTags = $result[1];
    $len_opened = count($openedTags);

    return (count($closedTags) == $len_opened) ? $string : false;
}

but it works sometimes good, but not for the example i had noticed at the top for example.

I am using symfony 4.2

2 Answers

I think the best way is render it and then check the error of it
test this code:

$html="<html><body><p>This is array.</p><br></body></html>";

libxml_use_internal_errors(true);

$dom = New DOMDocument();
$dom->loadHTML($html);

if (empty(libxml_get_errors())) {
  echo "This is a good HTML";
} else {
  echo "This not html";
}

output

This is a good HTML

Other Way

you can use simplexml_load_string to validate your html too, like this example:

function check($string){
    $start = strpos($string, '<');
    $end = strrpos($string, '>', $start);

    if ($end !== false) {
        $string = substr($string, $start);
    } else {
        $string = substr($string, $start, strlen($string) - $start);
    }

    $string = "<div>$string</div>";

    libxml_use_internal_errors(true);
    libxml_clear_errors();
    simplexml_load_string($string);

    return count(libxml_get_errors()) == 0;
}

$html="<html><body><p>This is array.</p></body></html>";

if (check($html)) {
  echo "This is a good HTML";
} else {
  echo "This not html";
}

But this way has a one problem and for example if you have a <br> tag in your code it return the false so I recommend to use the first way which is better

PHP's DOMDocument in conjunction with libxml can help with things like this. A simple function that will return true or false based upon whether libxml generates an error or not

<?php
    #The string to test
    $str='<h2 Article name</h2>This is an idea.<ul style="color:green;"><li>option 1</li><li>option 2</li><li>option 1<li></ul>';

    
    function isValidHTML($str=false){
        $base='
        <!DOCTYPE html>
        <html>
            <head>
                <title></title>
            </head>
            <body>%s</body>
        </html>';
        $html=sprintf( $base, $str );
        
        libxml_use_internal_errors( true );
        $dom=new DOMDocument;
            
        $dom->validateOnParse=false;
        $dom->recover=true;
        $dom->strictErrorChecking=false;
        $dom->loadHTML( $html );
        
        $errors=libxml_get_errors();
        libxml_clear_errors();
        
        return empty( $errors );
    }
    
    

    $valid=isValidHTML( $str );
    echo $valid ? 'Valid' : 'Bogus';
?>
Related