$Id$
++Introduction
XML_HTMLSax is a SAX based XML parser for badly formed XML documents,
such as HTML.
The original code base was developed by Alexander Zhukov and published at
http://sourceforge.net/projects/phpshelve/, who in turn was inspired by the
Python HTMLSax package.
Alexander kindly gave permission to modify the code and license for
inclusion in PEAR.
PEAR::XML_HTMLSax takes the last release from Sourceforge (HTMLSax2002082201)
and changes the API to make using HTMLSax very similar to using the native
PHP Expat extension, opening it up for use with projects like SAX filters:
http://phpxmlclasses.sourceforge.net/show_doc.php?class=class_sax_filters.html.
This version also fixes some bugs and adds further features such as the ability
to handle processing instructions and JSP/ASP markup.

++Uses
Some particular situations where XML_HTMLSax can be useful include;
- Converting HTML to XHTML
- Reading HTML based content from a database and converting to PDF (with
  help from a PDF generation library)
- Parsing ASP(.NET) and JSP pages.
- Creating a PHP-GTK based web browser? A PHP CSS Parser exists:
  http://www.phpclasses.org/browse.html/package/1081.html

++Features
- Won't "break" on badly formed XML. May in some instances get it "wrong"
  (see Limitations) but will continue parsing.
- Provides an API similar to the native PHP XML Expat extension
- In addition to handling basic XML elements attributes and data also
  capable of dealing with; 
   -Processing instructions e.g. <?php ?> / <?xml ?> etc. Within PI's
    entities are ignored (i.e. ignore < and > )
   - Escape markup e.g. <! > - note within <!-- --> HTML_Sax will ignore HTML
     entities but will pass everything within the <! > markup to the escape
     handler.
   - Regonizes JSP / ASP (JASP) marked up with <% %>. Note: You will need to
     deal with <%@ %> and <%= %> yourself. With JASP markup entities are
     ignored (i.e. ignore < and > )

++Usage Notes

- Comments <!-- -->, JASP tags <% %> and PI tags <? ?> may all contain < or > e.g.;
  <!-- This is an <html> tag -->
  Everything between <!-- and --> are regarded as contents of that element.
  Note that basic XML escapes like <! > will have the entities < > inside them
  parsed (this applies to DOCTYPE statements for example

- Comments are handled by the escape handler and will contain the !-- and -- from
  the beginning and end of the comment. You will need to strip these yourself.

- Comments trigger an additional character data callback after the escape handler
  has been triggered.

- JASP directives like <%@ and <%= will be not be regarded as special.
  I.e. you will get back the @ or % from the contents of the JASP block
  and have to deal with these yourself.

- For attributes which have just a name but no value e.g.
  <option value="bar" selected>
  HTMLSax will return true for that attribute name for the opening tag handler;

  function mYOpenTagHandler($parser,$name,$attrs) {
      print_r ( $attrs );
  }

  This would produce;

  Array
  (
      [value] => bar
      [selected] => true
  )

++ Limitations
- XML_HTMLSax does not regonize [CDATA[ ]] blocks

- XML_HTMLSax only supports use of PHP classes as callback handlers;
  there is no support for using PHP functions as handlers.

- <script /> elements containing < or > characters; these will be treated as new
  elements triggering the listeners. Possible workarounds might be to place the
  contents in an HTML comment e.g;
  <script>
  <!--
  document.write('<b>Hello World</b>');
  -->
  </script>
  Alternatively define open / close handlers which watch for <script /> elements
  as a special case, so that any further events triggered within them are handled
  as part of the <script /> element.

++ Example Use
Further examples are available in the examples directory of this package.

<?php
// Include required files
require_once('XML/State_Machine.php');
require_once('XML/Attributes_Parser.php');
require_once('XML/XML_HTMLSax.php');

// Define a customer handler class
class MyHandler {
    function MyHandler(){}

    // Opening tags
    function openHandler(& $parser,$name,$attrs) {
        echo ( 'Open Tag Handler: '.$name );
        echo ( 'Attrs:' );
        print_r($attrs);
    }

    // Closing tags
    function closeHandler(& $parser,$name) {
        echo ( 'Close Tag Handler: '.$name );
    }

    // Text node handler
    function dataHandler(& $parser,$data) {
        echo ( 'Data Handler: '.$data );
    }

    // XML escape handler (e.g. HTML comments)
    function escapeHandler(& $parser,$data) {
        echo ( 'Escape Handler: '.$data );
    }

    // Processing instruction handler
    function piHandler(& $parser,$target,$data) {
        echo ( 'PI Handler: '.$target.' - '.$data );
    }

    // JSP / ASP markup handler
    function jaspHandler(& $parser,$data) {
        echo ( 'Jasp Handler: '.$data );
    }
}

// Get some HTML document
$doc = file_get_contents('http://www.php.net');

// Instantiate the handler
$handler=new MyHandler;

// Instantiate the parser
$parser=& new XML_HTMLSax;

// Register the handler with the parser
$parser->set_object($handler);

// Set a parser option
$parser->set_option('trimDataNodes',1);

// Set the callback handlers (MyHandler methods)
$parser->set_element_handler('openHandler','closeHandler');
$parser->set_data_handler('dataHandler');
$parser->set_escape_handler('escapeHandler');
$parser->set_pi_handler('piHandler');
$parser->set_jasp_handler('jaspHandler');

// Parse the document
$parser->parse($doc);
?>