HTML Element Generator
In this kata, you will be creating a python function that will take arguments and turn them into an HTML element.
An HTML tag has three parts:

The opening tag, which consists of a tag name and potentially attributes, all in between angle brackets.
The element content, which is the data that is shown on the webpage.  This is in between the opening and closing tags.
And the closing tag, which is an opening angle bracket, a forward slash, the name of the tag, and a closing angle bracket


If you were to have multiple attributes, they would each appear with a single space separating them

Some tags do not require a closing tag.  These are called self-closing tags.  For this kata, any tag passed into the function without 'element content' (keyword arguments) will be treated in this way:  after the tag name (and any attributes), there will be a space and then a forward slash.  See the picture to the right.

Data will be passed into the html function as such: 

The first argument will be the tag name
Any other non-keyword arguments will be element content. If no element content is given, the return value will be expected to be a self-closing tag.  If more than one argument is given as element content, you will return multiple of the same element, just with different element content, separated by one or more newline characters.
Ex: 

<p class="paragraph-text" id="example">Hello World!</p>\n<p class="paragraph-text" id="example">This is HTML code!</p>

IMPORTANT:  Because class is a python keyword, and class is a very important HTML attribute, you will also have to implement a keyword argument named cls, as opposed to class.  This attribute will appear as class="variable" in the return value of your function
Any other keyword arguments of the function will be treated as attributes of the element.  The keyword is the attribute name (left of the equals sign), and the keyword's value is the attribute's value (right of the equals sign).
Element attributes will appear in the return value of your function in the order that they appear in the function's arguments when it is called.  If cls is an argument of the function, it will always appear first (before any other keyword arguments).
Several Examples are provided

```python

USER_FILENAME = "<user_code>"
import sys, json, builtins
import math, heapq, bisect, itertools, functools, collections, statistics, fractions, decimal, operator, array, random, re, string, os, pathlib
try:
    import resource as _res
except Exception:
    _res = None
from collections import Counter, defaultdict, deque, OrderedDict
from functools import lru_cache, reduce
from itertools import accumulate, permutations, combinations, product
from math import gcd, ceil, floor, sqrt
from decimal import Decimal
try:
    from typing import *
except Exception:
    pass
try:
    sys.setrecursionlimit(1_000_000)
except Exception:
    pass
try:
    import site as _site
    try:
        _sys_sites = _site.getsitepackages() if hasattr(_site, "getsitepackages") else []
        for _p in _sys_sites:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
    try:
        _usp = _site.getusersitepackages()
        if isinstance(_usp, str):
            _usp = [_usp]
        for _p in _usp:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
except Exception:
    pass

def _disabled_input(*args, **kwargs):
    raise RuntimeError("input() is disabled in callable mode")
builtins.input = _disabled_input

ns = {"__name__": "__judge__"}  # prevent if __name__ == "__main__" blocks
for _k, _v in list(globals().items()):
    if not _k.startswith("_"):
        ns[_k] = _v
_CODE = 'def stringify_attrs(attrs):\n  result = \'\'\n  for attr in attrs:\n    new_attr = attrs[attr]\n    if attr == \'cls\':\n      attr = \'class\'\n    result += attr + \'=\' + \'"\' + new_attr + \'"\' + \' \'\n  if not result:\n    return \'\'\n  return \' \' + result.strip()\n  \n\ndef html(tag, *bodies, **attrs):\n  if not bodies:\n    result = \'<\' + tag + stringify_attrs(attrs) + \' />\'\n    return result\n  result = \'\'\n  for body in bodies:\n    result += \'<\' + tag + stringify_attrs(attrs) + \'>\' + body + \'</\' + tag + \'>\' + \'\\n\'\n  return result.strip()'
_co = compile(_CODE, USER_FILENAME, "exec")
exec(_co, ns, ns)

_target = None
_fn_name = 'html'
if _fn_name:
    if "Solution" in ns:
        try:
            _obj = ns["Solution"]()
            if hasattr(_obj, _fn_name):
                _target = getattr(_obj, _fn_name)
        except Exception:
            _target = None
    if _target is None and _fn_name in ns and callable(ns[_fn_name]):
        _target = ns[_fn_name]
# Fallback: if there's exactly one user-defined function, use it
if _target is None:
    _cands = [v for k, v in ns.items() if callable(v) and getattr(v, "__module__", "") in ("__judge__", "__main__")]
    _user_funcs = [c for c in _cands if getattr(c, "__name__", "").startswith("_") is False]
    if len(_user_funcs) == 1:
        _target = _user_funcs[0]
if _target is None:
    raise RuntimeError(f"Could not resolve callable '{_fn_name}'")

_raw = sys.stdin.read().strip()
if _raw:
    _parsed = json.loads(_raw)
    if isinstance(_parsed, dict):
        _kwargs = _parsed.get("kwargs", {})
        _args = _parsed.get("args", [])
    else:
        _args, _kwargs = _parsed, {}
else:
    _args, _kwargs = [], {}
if not isinstance(_args, (list, tuple)):
    _args = [_args]
_res = _target(*_args, **_kwargs)
try:
    sys.stdout.write(repr(_res) + "\n")
except Exception:
    pass

```

Measured memory_bytes: 5717