def togpx(self):
        """Generate a GPX metadata element subtree.

        Returns:
            etree.Element: GPX metadata element
        """
        metadata = create_elem('metadata')
        if self.name:
            metadata.append(create_elem('name', text=self.name))
        if self.desc:
            metadata.append(create_elem('desc', text=self.desc))
        if self.author:
            element = create_elem('author')
            if self.author['name']:
                element.append(create_elem('name', text=self.author['name']))
            if self.author['email']:
                attr = dict(zip(self.author['email'].split('@'),
                                ('id', 'domain')))
                element.append(create_elem('email', attr))
            if self.author['link']:
                element.append(create_elem('link', text=self.author['link']))
            metadata.append(element)
        if self.copyright:
            if self.copyright['name']:
                author = {'author': self.copyright['name']}
            else:
                author = None
            element = create_elem('copyright', author)
            if self.copyright['year']:
                element.append(create_elem('year',
                                           text=self.copyright['year']))
            if self.copyright['license']:
                license = create_elem('license')
                element.append(license)
            metadata.append(element)
        if self.link:
            for link in self.link:
                if isinstance(link, basestring):
                    element = create_elem('link', {'href': link})
                else:
                    element = create_elem('link', {'href': link['href']})
                    if link['text']:
                        element.append(create_elem('text', text=link['text']))
                    if link['type']:
                        element.append(create_elem('type', text=link['type']))
                metadata.append(element)
        if isinstance(self.time, (time.struct_time, tuple)):
            text = time.strftime('%Y-%m-%dT%H:%M:%S%z', self.time)
        elif isinstance(self.time, utils.Timestamp):
            text = self.time.isoformat()
        else:
            text = time.strftime('%Y-%m-%dT%H:%M:%S%z')
        metadata.append(create_elem('time', text=text))
        if self.keywords:
            metadata.append(create_elem('keywords', text=self.keywords))
        if self.bounds:
            if not isinstance(self.bounds, dict):
                latitudes = list(map(attrgetter('latitude'), self.bounds))
                longitudes = list(map(attrgetter('longitude'), self.bounds))
                bounds = {
                    'minlat': str(min(latitudes)),
                    'maxlat': str(max(latitudes)),
                    'minlon': str(min(longitudes)),
                    'maxlon': str(max(longitudes)),
                }
            else:
                bounds = dict((k, str(v)) for k, v in self.bounds.items())
            metadata.append(create_elem('bounds', bounds))
        if self.extensions:
            element = create_elem('extensions')
            for i in self.extensions:
                element.append(i)
            metadata.append(self.extensions)
        return metadata