offline

Read HTML Metadata to Describe a Template

php, meta, html

For an application I had to write a selector for a bunch of *.html files in a folder.

That's fairly easy by doing:

foreach (glob("*.html") as $filename) {
	$files[] = '<option>'.basename($filename).'</option>';
}

echo sprintf('<select>%s</select>', implode('',$files));

and get a list of template filenames, that you can stuff in a <select>.

But with that, you have to use descriptive filenames and it's a bit of a bare-bone experience.

Why not add some meta information about the template file into the template file itself and use that for a richer presentation with some javascript dropdown like Select2?

For that we add some good old <meta> tags into the html>head and parse them with the get_meta_tags().

The template file look like this:

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="utf-8">

    <meta name="template:author" content="TEST, test@gmail.com">
    <meta name="template:name" content="Two Columns Layout">
    <meta name="template:description" content="This is a Two Column Layout">
    <meta name="template:icon" content="template-2col.svg">
    <meta name="template:color" content="orange">

    <title>{{ @page.title }} - {{ @page.subtitles }}</title>
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">
    <link rel="stylesheet" type="text/css" href="/assets/css/print.css">
    <style type="text/css">
        body {
            font-family: Roboto, sans-serif;
        }
    </style>
</head>
<body class="A4">
</body>
</html>

It includes a template author, the filename for an icon, stored somewhere on thee server and a title/description to show in the dropdown. All this information is used in the javascript dropdown/combobox.

Next you read all the HTML files in a directory and get_meta_tags while looping through them.

foreach (glob("/path/*.html") as $filename) {
	$meta[basename($filename)] = get_meta_tags($filename);
}

print_r($meta);

$meta now contains something like this:


(
	[alternative_template.html] => Array
	(
		[template:author] => TEST, test@gmail.com
		[template:name] => 2 Spalten Testlayout
		[template:description] => Zweispaltiges Template über die gesamte Breite
		[template:icon] => template-2col.svg
		[template:color] => orange
	)

	[print-wide.html] => Array
	(
		[template:author] => TEST, test@gmail.com
		[template:name] => 1 Spalte 
		[template:description] => Einspaltiges Template über die gesamte Breite
		[template:icon] => template-1col.svg
        [template:color] => #379a9a
    )

	[print.html] => Array
	(
		[template:author] => TEST, test@gmail.com
		[template:name] => 2 Spalten 
		[template:description] => Zweispaltiges Template über die gesamte Breite
		[template:icon] => template-2col.svg
        [template:color] => #000
    )

)

that lets you use the name of the template and an icon for the advanced combo box, select, dropdown... you name it, of your choice.

That's it!

There might be a case where you have to read the meta tags not from a HTML file, but from a <html> string.

Here it's best to parse the HTML with DOMDocument and access the <meta> tags with a xpath query.

See the following example.


$html = '
<!DOCTYPE html>
<html lang="de">
<head>
	<meta charset="utf-8">

	<meta name="template:author" content="TEST, test@gmail.com">
	<meta name="template:name" content="Two Columns Layout">
	<meta name="template:description" content="This is a Two Column Layout">
	<meta name="template:icon" content="template-2col.svg">
	<meta name="template:color" content="orange">
	
	<title>{{ @page.title }} - {{ @page.subtitles }}</title>
	<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">
	<link rel="stylesheet" type="text/css" href="/assets/css/print.css">
	<style type="text/css">
		body {
			font-family: Roboto, sans-serif;
		}
	</style>
</head>
<body class="A4">
</body>
</html>
';

function get_meta_tags_from_string($html) {
    $doc = new DOMDocument();
    libxml_use_internal_errors(true);
    $doc->loadHTML($html);
    libxml_clear_errors();
    
    $xpath = new DOMXPath($doc);
    $nodes = $xpath->query('//head/meta[@name]');
    $meta = [];
    
    foreach($nodes as $node) {
        $meta[$node->getAttribute('name')] = $node->getAttribute('content');
    }
    
    return $meta;
}

$meta = get_meta_tags_from_string($html);
Marcus Obst
Güterweg 89b
09474 Crottendorf
Germany

+49 37344 133407
info@marcus-obst.de