Łukasz Wróbel

From the archive

Tidying up HTML Code with Tidy PHP Extension

Written in 2008. Tools move on, but the basics here still hold.

Tidy is a quite powerful program which main purpose is to fix errors in HTML documents. TidyLib is a library version of Tidy written in C and by reason of easy C linkage, it can be used from within nearly any programming language, including PHP.

The common way to invoke Tidy functions from PHP is to use the Tidy extension, which can be easily enabled. Tidy extension has dual (both procedural and object-oriented) nature and from now on we’ll focus on the latter. To start work with Tidy, we simply need to create a new object:

<?php

  $tidy = new Tidy();

We can provide Tidy object with a string containing either file name or HTML document:

<?php

  $tidy->parseFile('myfile.html');

  // or

  $tidy->parseString('syntax <strong>error</small> <myowntag>my text</myowntag>');

In order to fix HTML code errors, we should invoke the cleanRepair() method. All in all, an example Tidy usage looks like this:

<?php

  $tidy = new Tidy();
  $tidy->parseString('syntax <strong>error</small> <myowntag>my text</myowntag>');
  $tidy->cleanRepair();

  echo $tidy;

When we look at the script output in web browser, we should see something familiar to this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title></title>
</head>
<body>
syntax <strong>error</strong> my text
</body>
</html>

There is much difference between the input and the output. At first glance we can see that the DOCTYPE and also html, head, title and body elements have been added. But let’s take a closer look. In our input string, there was a <strong> tag paired with a </small> tag instead of </strong> tag. Moreover, we used a <myowntag>, which is definitely not a valid HTML tag. As we can see, Tidy has got through it all without a hitch.

Admittedly, output code is valid, but it is not easily readable. Fortunately, Tidy comes to aid of making the code more readable using indentation, which is often called “beautifying”. We can change Tidy’s behavior by passing the $options array:

<?php

  $tidy = new Tidy();
  $options = array('indent' => true);

  $tidy->parseString('syntax <strong>error</small> <myowntag>my text</myowntag>', $options);
  $tidy->cleanRepair();

  echo $tidy;

The output is:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
  <head>
    <title></title>
  </head>
  <body>
    syntax <strong>error</strong> my text
  </body>
</html>

Looks better, doesn’t it? And Tidy has many more options to play with. If you are about to build the XML or XHTML documents, you might be interested in output-xml and output-xhtml options, just put them in the $options array and set their value to true:

<?php

  $tidy = new Tidy();
  $options = array('indent' => true, 'output-xhtml' => true);

  $tidy->parseString('syntax <strong>error</small> <myowntag>my text</myowntag>', $options);
  $tidy->cleanRepair();

  echo $tidy;

There are also some options that will be useful in reducing bandwidth usage. You may take a look at hide-comments, join-classes and join-styles options. It is advised to read the whole Tidy options list.

Tidy can be put inside your application in a painless way. Let’s say we have a template rendering mechanism, which outputs HTML code to the user. It would be a good idea to write a decorator:

<?php

  class TidyViewRenderer extends ViewRenderer {
    public function render($template) {
      ob_start();

      parent::render($template);

      $tidy = new Tidy;
      $tidy->parseString(ob_get_clean());
      $tidy->cleanRepair();

      echo $tidy;
    }
  }

We have just used two simple tricks. Firstly, our new render() method is a standard decorator pattern example: we’ve added some functionality (HTML errors fixing) to the inheriting class and the base class (ViewRenderer) doesn’t have to know anything about it and thus it doesn’t need to be changed. Secondly, we made a good use of PHP output buffering functions. They made our add-on transparent.

There is another thing you might want to know about Tidy. It can be used as a HTML validator due to its errorBuffer property which we can easily iterate through:

<?php

  $tidy = new Tidy();
  $tidy->parseString('syntax <strong>error</small> <myowntag>my text</myowntag>');
  $tidy->cleanRepair();

  if ($tidy->errorBuffer) {
    echo "There are some errors!\n";
    $errors = explode("\n", $tidy->errorBuffer);

    foreach ($errors as $error) {
      echo $error."\n";
    }
  } else {
    echo 'There are no errors.';
  }

This script displays a series of HTML warnings and errors:

There are some errors!
line 1 column 1 - Warning: missing <!DOCTYPE> declaration
line 1 column 1 - Warning: plain text isn't allowed in <head> elements
line 1 column 8 - Warning: replacing unexpected small by </small>
line 1 column 30 - Error: <myowntag> is not recognized!
line 1 column 30 - Warning: discarding unexpected <myowntag>
line 1 column 47 - Warning: discarding unexpected </myowntag>
line 1 column 1 - Warning: inserting missing 'title' element

It seems that we know much about Tidy library capabilities. Remember that the knowledge we gained can be used while writing applications in other languages. Good luck with tidying up the web!

This article was originally published under CC BY-SA 4.0.

11 comments

Comments are closed.

WhiteOctober 2015

Thanks a ton, bro! :)

Keep up the good work >>

AnonymousDecember 2014

where is tidy class? This is for apache server or i can add include im my scripts?

Łukasz WróbelauthorDecember 2014

**@brepair**:

> where is tidy class? This is for apache server or i can add include im my scripts?

Take a look at one of the comments above (the one including `sudo apt-get install php5-tidy`).

You can also enable the Tidy extension when compiling PHP. As the documentation states:

> This extension is bundled with PHP 5 and greater, and is installed using the `--with-tidy` configure option.

IglieousNovember 2013

I know i am late to the party(like 3 years) but I liked the article and the resources. Will use it for my parser. Cheers...

Asif KhanNovember 2012

Really this is way above my head. I am trying to learn coding but it is tough for an imbecile like me.
Do you know of any tool like http://validator.w3.org/ that can autofix a Wordpress site ? I have markup errors but am struggling to fix them, does any such tool exist ?
I would appreciate any suggestions.
Many Thanks
Regards

Łukasz WróbelauthorDecember 2012

**@Asif Khan:** I'm not too good at WordPress, but I found this plugin:

http://wordpress.org/extend...

It seems it suits your needs.

AnonymousSeptember 2012

Can you tell me how to install tidy on linux?

Łukasz WróbelauthorSeptember 2012

**@Thiet ke web**: Answer strongly depends on the specific distribution you use. On Ubuntu, the following command:

sudo apt-get install php5-tidy

is all what it takes to use Tidy from within PHP. It not only installs the extension itself, but also makes sure that libtidy is present. Of course, it works only if PHP is installed as a package. If it's not the case, then you have to use PECL or compile the extension manually.

Show all 11 comments

TWiStErDecember 2010

Hi!

There is an option to force the output, when you got errors like:
"Error: is not recognized!"

force-output:
http://tidy.sourceforge.net...
"This option specifies if Tidy should produce output even if errors are encountered. Use this option with care - if Tidy reports an error, this means Tidy was not able to, or is not sure how to, fix the error, so the resulting output may not reflect your intention."

HTH,
+Robi

MarkusNovember 2008

I like the 'indent' option; saves me having to format the HTML myself. Chore.

Łukasz WróbelauthorNovember 2008

On the contrary, there are many options (hide-comments, drop-empty-paras, merge-divs and so on) that will let us save the bandwidth by sacrificing readability. Everything depends on the goal we want to achieve and this is the best proof of Tidy's flexibility.