Thanks for your input guys, I don't think either of these will do exactly what I need though. To put it in context, here is a scaled down version of the class and an example piece of html to put in it. Forgive my lazy coding shortcuts (like defining , so I don't have to quote it). It is just a simple html parser, so that I can manipulate a html dom with php (say curl in a page and alter a div). I think it is elegant, except the aforementioned eval lines. I left out the meat of it, but this condenses an html string to an array with tags at '' and attributes at '@'
class pxhtml
{
public static $tag_stack;
public static $pdom;
public static $iteration;
public static $depth = 0; //current dom depth
public static $last_tag_closed; // for debugging
public function __construct( $data = '' )
{
define('tag', '|\<([\/]*)(\w+)([^\/\>]*)([/]*)\>([^<]*)|'); //preg exp
define('attributes', '|(\w+)[ ]*\=[ ]*["]*(\w+)["]*|x'); //preg exp
define('_', '_'); //just for less typing
$this->iteration = array( ); // iterations by depth
$this->pdom = array( ); // the html dom
$this->tag_stack = array( ); // a list of open tags
if( is_string( $data ) && $data != '' )
{
$this->process_html( $data );
}
return $this->pdom;
}
public function process_atts( $string )
{//turns attributes string into an array
$array = array();
preg_match_all( attributes, $string, $atts_array, PREG_SET_ORDER );
$return_array = array();
foreach($atts_array as $a)
{
$return_array[$a[1]] = $a[2];
}
return $return_array;
}
public function process_html( $string )
{//tag by tag processing of string
$elements = array();
//find all the tags and surrounding text
preg_match_all( tag, $string, $elements, PREG_SET_ORDER );
foreach( $elements as $element )
{
$this->pdom_append( $element );
}
}
private function pdom_append( $element )
{ // determines tag type and organizes the structure
list( $full_tag, $closing_tag, $tag, $atts, $empty_tag, $text ) = $element;
if( !$closing_tag & !$empty_tag )
{ // opening tag
$this->open_tag( $tag, $atts, $text );
}
elseif ( $closing_tag )
{ // closing tag
$this->close_tag( $tag, $text );
}
elseif ( $empty_tag )
{ // empty tag
$this->empty_tag( $tag, $atts, $text );
}
}
private function open_tag( $tag, $atts = '', $text = '' )
{ // adds an open tag, attributes, and text node to the dom
$this->tag_stack[] = $tag;
$this->depth = count( $this->tag_stack ) - 1;
$this->iteration[$this->depth] = ( isset( $this->iteration[$this->depth] ) ) ? $this->iteration[$this->depth] + 1 : 0;
$this->depth++;
$this->set( array( $tag, $atts, $text ) );
$this->iteration[$this->depth] = 0;
}
private function close_tag( $text = '' )
{ // close out the last tag
$this->last_tag_closed = array_pop( $this->tag_stack );
array_pop( $this->iteration );
//unset( $this->iteration[$this->depth] );
$this->depth = count( $this->tag_stack );
if( trim( $text ) != '' )
{
$this->iteration[$this->depth]++;
$this->add_text( $text );
}
}
private function empty_tag( $tag, $atts = '', $text = '' )
{ // open and close tag, needs work still
$this->open_tag( $tag, $atts, '<!-- empty tag -->' );
$this->close_tag( $tag, $text );
}
private function set( $array )
{// set the current pdom node
$keys = implode( '][', $this->iteration );
$eval_str = '$this->pdom[' . $keys . '] = array( _ => $array[0] ); ';
if( trim( $array[1] ) != '' )
{
$eval_str .= '$this->pdom[' . $keys . '][\'@\'] = $this->process_atts( $array[1] ); ';
}
if( trim( $array[2] ) != '' )
{
$this->iteration[$this->depth] = 0;
$eval_str .= '$this->pdom[' . $keys . '][0] = $array[2]; ';
}
eval( $eval_str );
}
private function add_text( $text )
{ // add a text node at current pdom node
$keys = implode( '][', $this->iteration );
$this->iteration[$this->depth] = ( isset( $this->iteration[$this->depth] ) ) ? $this->iteration[$this->depth] + 1 : 0;
$eval_str .= '$this->pdom[' . $keys . '] = $text; ';
eval( $eval_str );
}
}
[php]...[/code] tags added by moderator