Controlling Taxonomy Category listings to hide and unhide specifics

I’ve made some progress based on walker classes but havent gotten ti working quite as needed because wordpress doesnt appear to handle the root nodes of the taxonomy tree in the same way as the child ones.

As a result, it prunes the end menu items, but if the parent of that node is a root level node, it prunes the node and leaves an empty ul element behind, <ul></ul>. The code that fixes this issue on child nodes does not work for a root node, resulting in the whole structure flattening with no submenus

class Post_Category_Walker extends Walker_Category {

    private $term_ids = array();
    function __construct( /*$post_id,*/ $taxonomy )  {
        // fetch the list of term ids for the given post
        $this->taxterms = get_terms( $taxonomy);
        $this->noshow = array();
    }
    function isdisplayable( $element, &$children_elements, $args ){
        $id = $element->term_id;
        if(in_array($element->term_id, $this->noshow)){
            return false;
        }
        $display = true;
        if($element->parent != 0){
            $display = false;
            if ( isset( $children_elements[ $id ] ) ) {
                $display = true;
            }
        }
        if($depth == 0){
            $display = true;
        }
        return $display;
    }
    function hasChildren( $element/*, &$children_elements*/){
        foreach($this->taxterms as $term){
            if($term->parent == $element->term_id){
                return true;
            }
        }
        return false;//(isset($children_elements[$element->term_id]));
    }
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        $display = $this->isdisplayable( $element, $children_elements, $args );
        $id = $element->term_id;
        if($element->parent != 0){

            if($this->hasChildren($element)){ //isset( $children_elements[ $id ] ) ) {
                $endnode = true;
                //print_r($children_elements[ $id ]);
                foreach($this->taxterms as $child){
                    if($child->parent == $element->term_id){
                        if($this->hasChildren($child)){
                            $endnode = false;
                            break;
                        }
                    }
                }
                if($endnode == true){
                    //$children_elements = NULL;
                    unset( $children_elements[ $id ] );
                    $newlevel = false;
                    $args[0]['has_children'] = 0;
                }
            }
        }else{
            // WordPress separates out the terms into top level and child terms,
            // making the top level terms very costly as it passes in an empty 
            // array as the children_elements unlike the other terms
            //if($this->hasChildren($element)){
                foreach($this->taxterms as $term){
                    if($term->parent == $element->term_id){
                        if(!$this->hasChildren($term)){
                            $this->noshow[] = $term->term_id;
                            unset($newlevel);
                            $args[0]['has_children'] = 0;
                        }
                    }
                }
            //}
        }

        if ( $display )
            parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }
}
$a = array(
    'title_li'  =>  '',
    'taxonomy'  =>  'productcategory',
    'walker'    =>  new Post_Category_Walker('productcategory')
);
wp_list_categories( $a );

A temporary workaround is to remove them via the following jquery snippet:

$("ul").each(
  function() {
    var elem = $(this);
    if (elem.children().length == 0) {
      elem.remove();
    }
  }
);