Don’t display taxonomy if empty

What you need is set the show_option_none to a string easily recognizable and then add the result of wp_list_categories to the content only if it it does not contain that string..

So your foreach loop shoul look somethinlg like

foreach( $taxonomies as $taxonomy ) {           
  $args = array(
    'orderby' => 'name',
    'echo' => false,
    'taxonomy' => $taxonomy->name,
    'title_li' => '<span class="taxonomy_title">' . __( $taxonomy->labels->name, 'your-themes-text-domain' ) . '</span>',
    'show_option_none' => '%%NOCAT%%'
  );
  $list = wp_list_categories( $args );
  $empty = (bool) substr_count( strip_tags($list), '%%NOCAT%%');
  $content .= ! $empty ? '<ul>' . $list . '</ul>' : '';              
} 

In this way if your custom tax has no terms the result of wp_list_categories is not added to the html output.


Additional suggestions

Just few days ago I experienced an issue using something like

add_filter( 'the_content', 'display_post_taxonomies' );

because some SEO plugins use get_the_excerpt to fill the meta description in the <head> section of the page.
Problem is that get_the_excerpt, when there is no manual excerpt for post, call wp_trim_excerpt and this function fires the_content hook. Result: you will find the list of your taxonomy in the head of your page: that’s bad.

Also you should note that 'the_content' hook can be fired not only in main query, so if you have some secondary queries on sidebar or footer your function will be called again there: that’s bad.

What I suggest is where you have

if( is_single() ) {

replace with

if( is_single() && did_action('loop_start') ) {

This prevent function run in the <head> section.

After that, remove the filter befor return the content, in this way you are sure the filter run once, so

return $content;

became

remove_filter( 'the_content', 'display_post_taxonomies' );
return $content;