Set media metadata (i.e. “dimensions” field) on SVG file after extracting it with a filter

The wp_update_attachment_metadata filter fires every time you upload an image through media library (specifically every time wp_update_attachment_metadata function is being called).

So when an svg file is uploaded we check if the file has the desired metadata, the width and height. If not, we generate the metadata as you did in your wp_get_attachment_image_src filter. Now that the metadata are saved we can call functions like wp_get_attachment_image_src and get the metada without the need to filter those functions.

Be aware of the problem of uploading svg files in the latest WordPress version (4.7.2). It supposed to be fixed in 4.7.3

Lastly I would like to warn you about the potential security risks (XSS attacks) that svg files expose. More here and here.

function svg_meta_data($data, $id){

    $attachment = get_post($id); // Filter makes sure that the post is an attachment
    $mime_type = $attachment->post_mime_type; // The attachment mime_type

    //If the attachment is an svg

    if($mime_type == 'image/svg+xml'){

        //If the svg metadata are empty or the width is empty or the height is empty
        //then get the attributes from xml.

        if(empty($data) || empty($data['width']) || empty($data['height'])){

            $xml = simplexml_load_file(wp_get_attachment_url($id));
            $attr = $xml->attributes();
            $viewbox = explode(' ', $attr->viewBox);
            $data['width'] = isset($attr->width) && preg_match('/\d+/', $attr->width, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[2] : null);
            $data['height'] = isset($attr->height) && preg_match('/\d+/', $attr->height, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[3] : null);
        }

    }

    return $data;

}

add_filter('wp_update_attachment_metadata', 'svg_meta_data', 10, 2);