def serialize_table(ctx, document, table, root):
    """Serializes table element.
    """

    # What we should check really is why do we pass None as root element
    # There is a good chance some content is missing after the import

    if root is None:
        return root

    if ctx.ilvl != None:
        root = close_list(ctx, root)
        ctx.ilvl, ctx.numid = None, None

    _table = etree.SubElement(root, 'table')
    _table.set('border', '1')
    _table.set('width', '100%')

    style = get_style(document, table)

    if style:
        _table.set('class', get_css_classes(document, style))

    for rows in table.rows:
        _tr = etree.SubElement(_table, 'tr')

        for cell in rows:
            _td = etree.SubElement(_tr, 'td')

            if cell.grid_span != 1:
                _td.set('colspan', str(cell.grid_span))

            if cell.row_span != 1:
                _td.set('rowspan', str(cell.row_span))

            for elem in cell.elements:
                if isinstance(elem, doc.Paragraph):
                    _ser = ctx.get_serializer(elem)
                    _td = _ser(ctx, document, elem, _td, embed=False)

            if ctx.ilvl != None:
#                root = close_list(ctx, root)
                _td = close_list(ctx, _td)

                ctx.ilvl, ctx.numid = None, None

            fire_hooks(ctx, document, table, _td, ctx.get_hook('td'))
        fire_hooks(ctx, document, table, _td, ctx.get_hook('tr'))

    fire_hooks(ctx, document, table, _table, ctx.get_hook('table'))

    return root
Serializes table element.